--- tags: [后端, 部署, 运维, 基础] create time: 2026-04-24 18:41 --- # 部署与运维基础 ## 概述 写完代码只是第一步,让代码在生产环境中稳定运行才是真正的工作。部署与运维涵盖了从构建、容器化、反向代理到监控的所有环节。 思考题:为什么本地运行正常的代码,部署到服务器就出问题?最常见的坑有哪些? ## 正文 ### 1. 环境变量 — 环境差异的桥梁 ```bash # 不同环境配置不同的变量 # .env.production DATABASE_HOST=db.production.com DATABASE_PORT=5432 DATABASE_USER=admin DATABASE_PASSWORD=secret JWT_SECRET=very-long-secret-key PORT=8080 LOG_LEVEL=warn ``` ```go // Go 中读取环境变量 import "os" func main() { port := os.Getenv("PORT") if port == "" { port = "8080" // 默认值 } logLevel := os.Getenv("LOG_LEVEL") // ... } ``` > **核心原则:** 12-Factor App 原则——配置必须存储在环境变量中,绝不能硬编码到代码里。同一份代码,换环境只需换变量。 > **提问:** 为什么数据库密码不能写在代码里或提交到 Git?`.env` 文件应该加入 `.gitignore` 吗? ### 2. Nginx — 反向代理与负载均衡 ```nginx server { listen 80; server_name api.example.com; # 反向代理到 Go 服务 location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } # 前端静态文件 location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; # SPA 路由支持 } # 静态资源缓存 location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { expires 30d; add_header Cache-Control "public, immutable"; } } ``` ```mermaid sequenceDiagram participant C as 客户端 participant N as Nginx:80 participant G as Go:8080 participant F as 静态文件 C->>N: GET /api/users N->>G: proxy_pass → :8080/api/users G-->>N: JSON 响应 N-->>C: 返回数据 C->>N: GET /index.html N->>F: 读取本地文件 F-->>N: HTML 文件 N-->>C: 返回页面 ``` > **思考:** Nginx 既能做反向代理又能提供静态文件服务。为什么要把 API 和前端静态文件放在一起部署,而不是分开? ### 3. Docker — 容器化部署 ```dockerfile # 多阶段构建(减小镜像体积) FROM golang:1.22-alpine AS builder WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . RUN CGO_ENABLED=0 GOOS=linux go build -o server . # 最终镜像 FROM alpine:3.19 WORKDIR /app COPY --from=builder /app/server . EXPOSE 8080 # 安全:不用 root 运行 RUN adduser -D appuser USER appuser CMD ["./server"] ``` ```bash # 构建镜像 docker build -t myapp:latest . # 运行容器 docker run -d \ --name myapp \ -p 8080:8080 \ -e DATABASE_HOST=db \ -e JWT_SECRET=secret \ myapp:latest ``` ### 4. Docker Compose — 多服务编排 ```yaml version: '3.8' services: app: build: . ports: - "8080:8080" environment: - DATABASE_HOST=postgres - DATABASE_PORT=5432 - DATABASE_USER=postgres - DATABASE_PASSWORD=secret depends_on: - postgres restart: unless-stopped postgres: image: postgres:16-alpine environment: POSTGRES_DB: myapp POSTGRES_PASSWORD: secret volumes: - pgdata:/var/lib/postgresql/data restart: unless-stopped nginx: image: nginx:alpine ports: - "80:80" volumes: - ./nginx.conf:/etc/nginx/nginx.conf depends_on: - app restart: unless-stopped volumes: pgdata: ``` ### 5. 持续集成/持续部署(CI/CD)基础 ```yaml # .github/workflows/deploy.yml name: Deploy on: push: branches: [main] jobs: build-and-deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build Docker image run: docker build -t myapp:${{ github.sha }} . - name: Push to registry run: | docker tag myapp:${{ github.sha }} registry.example.com/myapp:${{ github.sha }} docker push registry.example.com/myapp:${{ github.sha }} - name: Deploy to server run: ssh deploy@server "docker pull registry.example.com/myapp:${{ github.sha }} && docker-compose up -d" ``` ### 6. 常用运维命令 ```bash # Docker 常用 docker ps # 查看运行中的容器 docker logs -f myapp # 查看容器日志 docker exec -it myapp sh # 进入容器 docker-compose up -d # 启动所有服务 # Go 服务 kill -SIGTERM $(pgrep server) # 优雅停止 go tool pprof http://localhost:6060/debug/pprof/heap # 内存分析 ``` ## 关联笔记 - [[Go 后端基础]] — Go 应用的代码实现 - [[API 设计]] — 部署的 API 需要按规范设计 - [[30.areas/finance/Investment lessons/2024.Current trading lessons.md]]