405 部署与运维
用 Codex 生成 Dockerfile、CI/CD 配置和监控方案
学习目标
完成本课程后,你将能够:
一、Docker 容器化
用 Codex 生成 Dockerfile
/init 请为 Next.js + Express 项目生成 Docker 配置:
- 前端用多阶段构建,输出静态文件
- 后端用 Node.js 20 Alpine
- 前端静态文件由 Nginx 托管
- 添加健康检查
- 非 root 用户运行前端 Dockerfile(多阶段构建)
# frontend/Dockerfile
# Stage 1: 构建
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# Stage 2: 运行
FROM nginx:1.25-alpine AS runner
COPY --from=builder /app/out /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget -qO- http://localhost:80/health || exit 1
EXPOSE 80
USER nginx
CMD ["nginx", "-g", "daemon off;"]后端 Dockerfile
# backend/Dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 expressjs
COPY --from=builder --chown=expressjs:nodejs /app/dist ./dist
COPY --from=builder --chown=expressjs:nodejs /app/node_modules ./node_modules
COPY --from=builder --chown=expressjs:nodejs /app/prisma ./prisma
COPY --from=builder --chown=expressjs:nodejs /app/package.json ./
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget -qO- http://localhost:3000/api/health || exit 1
EXPOSE 3000
USER expressjs
CMD ["node", "dist/index.js"]Docker Compose 编排
# docker-compose.yml
version: '3.8'
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: taskflow
POSTGRES_USER: app
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d taskflow"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
volumes:
- redisdata:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
backend:
build: ./backend
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
environment:
DATABASE_URL: postgresql://app:${DB_PASSWORD}@postgres:5432/taskflow
REDIS_URL: redis://redis:6379
ports:
- "3000:3000"
frontend:
build: ./frontend
depends_on:
- backend
ports:
- "80:80"
volumes:
pgdata:
redisdata:二、CI/CD 流水线
GitHub Actions 配置
# .github/workflows/ci-cd.yml
name: CI/CD Pipeline
on:
push:
branches: [main, staging]
pull_request:
branches: [main]
jobs:
lint-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Lint
run: npm run lint
- name: Type check
run: npm run type-check
- name: Unit tests
run: npm run test -- --coverage
- name: Upload coverage
uses: actions/upload-artifact@v4
with:
name: coverage
path: coverage/
build-and-push:
needs: lint-and-test
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/staging'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push backend
uses: docker/build-push-action@v5
with:
context: ./backend
push: true
tags: ghcr.io/${{ github.repository }}/backend:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Build and push frontend
uses: docker/build-push-action@v5
with:
context: ./frontend
push: true
tags: ghcr.io/${{ github.repository }}/frontend:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
deploy-staging:
needs: build-and-push
if: github.ref == 'refs/heads/staging'
runs-on: ubuntu-latest
environment: staging
steps:
- name: Deploy to staging
run: |
echo "Deploying to staging server..."
# 通过 SSH 或 Webhook 触发部署
deploy-production:
needs: build-and-push
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: production
steps:
- name: Deploy canary
run: |
echo "Deploying canary (10% traffic)..."
# 金丝雀部署 10%
- name: Health check
run: |
sleep 30
curl -f http://canary.example.com/api/health || exit 1
- name: Full rollout
run: |
echo "Rolling out to 100%..."
# 全量上线三、监控与日志
应用监控指标
用 Codex 生成 Prometheus 指标端点:
请为 Express 后端添加 Prometheus 监控:
- HTTP 请求计数、延迟、状态码分布
- 数据库查询耗时
- 活跃连接数
- 内存和 CPU 使用率// backend/src/middleware/metrics.ts
import { Registry, Counter, Histogram, Gauge } from 'prom-client';
export const registry = new Registry();
export const httpRequestDuration = new Histogram({
name: 'http_request_duration_seconds',
help: 'HTTP 请求耗时',
labelNames: ['method', 'route', 'status'],
buckets: [0.01, 0.05, 0.1, 0.5, 1, 2, 5],
registers: [registry],
});
export const httpRequestTotal = new Counter({
name: 'http_requests_total',
help: 'HTTP 请求总数',
labelNames: ['method', 'route', 'status'],
registers: [registry],
});
export const dbQueryDuration = new Histogram({
name: 'db_query_duration_seconds',
help: '数据库查询耗时',
labelNames: ['operation', 'model'],
registers: [registry],
});结构化日志
// backend/src/utils/logger.ts
import pino from 'pino';
export const logger = pino({
level: process.env.LOG_LEVEL || 'info',
transport: process.env.NODE_ENV === 'development'
? { target: 'pino-pretty', options: { colorize: true } }
: undefined,
serializers: {
req: (req) => ({
method: req.method,
url: req.url,
userId: req.user?.id,
}),
err: pino.stdSerializers.err,
},
redact: ['req.headers.authorization', 'req.headers.cookie'],
});四、金丝雀部署
部署策略
全量部署风险:
- Bug 影响所有用户
- 回滚需数分钟
- 无 A/B 验证窗口
金丝雀部署流程:
1. 部署新版本到 10% 实例
2. 观察 15 分钟(错误率、延迟、CPU)
3. 指标正常 → 扩展到 50%
4. 再观察 10 分钟
5. 指标正常 → 全量上线
6. 指标异常 → 自动回滚用 Codex 生成金丝雀脚本
请生成 Kubernetes 金丝雀部署配置:
- 使用 Istio VirtualService 控制流量权重
- 初始 10%,逐步提升到 100%
- 基于 Prometheus 指标自动判断是否回滚
- 回滚阈值为错误率 > 5% 或 P99 延迟 > 2s五、实战练习
练习 1:生成完整部署配置
/init 为以下部署场景生成配置:
- 生产环境:Kubernetes + Helm
- 需要配置 Ingress、HPA、PDB
- 环境变量通过 Secret 注入
- 挂载 ConfigMap 作为 Nginx 配置练习 2:告警规则配置
请为任务管理平台配置 Prometheus 告警规则:
- API 错误率 > 5%(持续 5 分钟)
- P95 延迟 > 1s
- 数据库连接池耗尽
- 磁盘使用率 > 85%
- 证书过期 < 7 天
告警通知到 Slack + 邮件练习 3:灾备演练
请设计灾备演练方案:
1. 主数据库故障切换流程
2. 多可用区故障转移
3. RTO < 5 分钟,RPO < 1 分钟
4. 演练脚本和检查清单六、本课总结
**核心要点:**
- 多阶段 Docker 构建缩小镜像体积,非 root 用户提升安全性
- CI/CD 流水线分 lint → test → build → deploy 四个阶段
- 监控三件套:Prometheus 指标 + 结构化日志 + 分布式追踪
- 金丝雀部署用流量权重逐步切换,配合自动回滚降低风险
- 备份、监控、告警、灾备是一个整体,缺一不可
**下一步:** 模块 406 — 项目复盘与优化