$npx -y skills add virgo777/buddyme --skill deployment-patternsDeployment workflows, CI/CD pipeline patterns, Docker containerization, health checks, rollback strategies, and production readiness checklists for web applications.
| 1 | # 部署模式 (Deployment Patterns) |
| 2 | |
| 3 | 生产部署工作流与 CI/CD 最佳实践。 |
| 4 | |
| 5 | ## 何时激活 |
| 6 | |
| 7 | - 设置 CI/CD 流水线 (Pipelines) |
| 8 | - 对应用程序进行 Docker 容器化 |
| 9 | - 规划部署策略(蓝绿部署、金丝雀部署、滚动更新) |
| 10 | - 实现健康检查 (Health Checks) 与就绪探针 (Readiness Probes) |
| 11 | - 准备生产发布 |
| 12 | - 配置环境特定的设置 |
| 13 | |
| 14 | ## 部署策略 (Deployment Strategies) |
| 15 | |
| 16 | ### 滚动部署 (Rolling Deployment) - 默认 |
| 17 | |
| 18 | 逐渐替换实例 —— 在滚动更新期间,旧版本和新版本同时运行。 |
| 19 | |
| 20 | ``` |
| 21 | 实例 1: v1 → v2 (首先更新) |
| 22 | 实例 2: v1 (仍在运行 v1) |
| 23 | 实例 3: v1 (仍在运行 v1) |
| 24 | |
| 25 | 实例 1: v2 |
| 26 | 实例 2: v1 → v2 (其次更新) |
| 27 | 实例 3: v1 |
| 28 | |
| 29 | 实例 1: v2 |
| 30 | 实例 2: v2 |
| 31 | 实例 3: v1 → v2 (最后更新) |
| 32 | ``` |
| 33 | |
| 34 | **优点:** 零停机时间,渐进式推出 |
| 35 | **缺点:** 两个版本同时运行 —— 要求变更必须向后兼容 |
| 36 | **适用场景:** 标准部署,向后兼容的变更 |
| 37 | |
| 38 | ### 蓝绿部署 (Blue-Green Deployment) |
| 39 | |
| 40 | 运行两个完全相同的环境。原子化地切换流量。 |
| 41 | |
| 42 | ``` |
| 43 | 蓝色环境 (v1) ← 流量接入 |
| 44 | 绿色环境 (v2) 空闲,运行新版本 |
| 45 | |
| 46 | # 验证后: |
| 47 | 蓝色环境 (v1) 空闲 (变为备用) |
| 48 | 绿色环境 (v2) ← 流量接入 |
| 49 | ``` |
| 50 | |
| 51 | **优点:** 瞬时回滚(切换回蓝色环境),干净的切割 |
| 52 | **缺点:** 部署期间需要 2 倍的基础设施资源 |
| 53 | **适用场景:** 关键服务,对问题零容忍 |
| 54 | |
| 55 | ### 金丝雀部署 (Canary Deployment) |
| 56 | |
| 57 | 首先将小部分比例的流量路由到新版本。 |
| 58 | |
| 59 | ``` |
| 60 | v1: 95% 流量 |
| 61 | v2: 5% 流量 (金丝雀) |
| 62 | |
| 63 | # 如果指标良好: |
| 64 | v1: 50% 流量 |
| 65 | v2: 50% 流量 |
| 66 | |
| 67 | # 最终: |
| 68 | v2: 100% 流量 |
| 69 | ``` |
| 70 | |
| 71 | **优点:** 在全量推出前通过真实流量发现问题 |
| 72 | **缺点:** 需要流量切分基础设施和监控 |
| 73 | **适用场景:** 高流量服务,高风险变更,特性标志 (Feature Flags) |
| 74 | |
| 75 | ## Docker |
| 76 | |
| 77 | ### 多阶段 Dockerfile (Node.js) |
| 78 | |
| 79 | ```dockerfile |
| 80 | # 阶段 1: 安装依赖 |
| 81 | FROM node:22-alpine AS deps |
| 82 | WORKDIR /app |
| 83 | COPY package.json package-lock.json ./ |
| 84 | RUN npm ci --production=false |
| 85 | |
| 86 | # 阶段 2: 构建 |
| 87 | FROM node:22-alpine AS builder |
| 88 | WORKDIR /app |
| 89 | COPY --from=deps /app/node_modules ./node_modules |
| 90 | COPY . . |
| 91 | RUN npm run build |
| 92 | RUN npm prune --production |
| 93 | |
| 94 | # 阶段 3: 生产镜像 |
| 95 | FROM node:22-alpine AS runner |
| 96 | WORKDIR /app |
| 97 | |
| 98 | RUN addgroup -g 1001 -S appgroup && adduser -S appuser -u 1001 |
| 99 | USER appuser |
| 100 | |
| 101 | COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules |
| 102 | COPY --from=builder --chown=appuser:appgroup /app/dist ./dist |
| 103 | COPY --from=builder --chown=appuser:appgroup /app/package.json ./ |
| 104 | |
| 105 | ENV NODE_ENV=production |
| 106 | EXPOSE 3000 |
| 107 | |
| 108 | HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ |
| 109 | CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1 |
| 110 | |
| 111 | CMD ["node", "dist/server.js"] |
| 112 | ``` |
| 113 | |
| 114 | ### 多阶段 Dockerfile (Go) |
| 115 | |
| 116 | ```dockerfile |
| 117 | FROM golang:1.22-alpine AS builder |
| 118 | WORKDIR /app |
| 119 | COPY go.mod go.sum ./ |
| 120 | RUN go mod download |
| 121 | COPY . . |
| 122 | RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /server ./cmd/server |
| 123 | |
| 124 | FROM alpine:3.19 AS runner |
| 125 | RUN apk --no-cache add ca-certificates |
| 126 | RUN adduser -D -u 1001 appuser |
| 127 | USER appuser |
| 128 | |
| 129 | COPY --from=builder /server /server |
| 130 | |
| 131 | EXPOSE 8080 |
| 132 | HEALTHCHECK --interval=30s --timeout=3s CMD wget -qO- http://localhost:8080/health || exit 1 |
| 133 | CMD ["/server"] |
| 134 | ``` |
| 135 | |
| 136 | ### 多阶段 Dockerfile (Python/Django) |
| 137 | |
| 138 | ```dockerfile |
| 139 | FROM python:3.12-slim AS builder |
| 140 | WORKDIR /app |
| 141 | RUN pip install --no-cache-dir uv |
| 142 | COPY requirements.txt . |
| 143 | RUN uv pip install --system --no-cache -r requirements.txt |
| 144 | |
| 145 | FROM python:3.12-slim AS runner |
| 146 | WORKDIR /app |
| 147 | |
| 148 | RUN useradd -r -u 1001 appuser |
| 149 | USER appuser |
| 150 | |
| 151 | COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages |
| 152 | COPY --from=builder /usr/local/bin /usr/local/bin |
| 153 | COPY . . |
| 154 | |
| 155 | ENV PYTHONUNBUFFERED=1 |
| 156 | EXPOSE 8000 |
| 157 | |
| 158 | HEALTHCHECK --interval=30s --timeout=3s CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health/')" || exit 1 |
| 159 | CMD ["gunicorn", "config.wsgi:application", "--bind", "0.0.0.0:8000", "--workers", "4"] |
| 160 | ``` |
| 161 | |
| 162 | ### Docker 最佳实践 |
| 163 | |
| 164 | ``` |
| 165 | # 推荐做法 (GOOD practices) |
| 166 | - 使用具体的版本标签 (node:22-alpine, 而非 node:latest) |
| 167 | - 使用多阶段构建以最小化镜像大小 |
| 168 | - 以非 root 用户运行 |
| 169 | - 首先复制依赖文件(利用层缓存) |
| 170 | - 使用 .dockerignore 排除 node_modules, .git, tests |
| 171 | - 添加 HEALTHCHECK 指令 |
| 172 | - 在 docker-compose 或 k8s 中设置资源限制 |
| 173 | |
| 174 | # 错误做法 (BAD practices) |
| 175 | - 以 root 用户运行 |
| 176 | - 使用 :latest 标签 |
| 177 | - 在一个 COPY 层中复制整个仓库 |
| 178 | - 在生产镜像中安装开发依赖 |
| 179 | - 在镜像中存储机密信息(应使用环境变量或机密管理器) |
| 180 | ``` |
| 181 | |
| 182 | ## CI/CD 流水线 (CI/CD Pipeline) |
| 183 | |
| 184 | ### GitHub Actions (标准流水线) |
| 185 | |
| 186 | ```yaml |
| 187 | name: CI/CD |
| 188 | |
| 189 | on: |
| 190 | push: |
| 191 | branches: [main] |
| 192 | pull_request: |
| 193 | branches: [main] |
| 194 | |
| 195 | jobs: |
| 196 | test: |
| 197 | runs-on: ubuntu-latest |
| 198 | steps: |
| 199 | - uses: actions/checkout@v4 |
| 200 | - uses: actions/setup-node@v4 |
| 201 | with: |
| 202 | node-version: 22 |
| 203 | cache: npm |
| 204 | - run: npm ci |
| 205 | - run: npm run lint |
| 206 | - run: npm run typecheck |
| 207 | - run: npm test -- --coverage |
| 208 | - uses: actions/upload-artifact@v4 |
| 209 | if: always() |
| 210 | with: |
| 211 | name: coverage |
| 212 | path: coverage/ |
| 213 | |
| 214 | build: |
| 215 | needs: test |
| 216 | runs-on: ubuntu-latest |
| 217 | if: github.ref == 'refs/heads/main' |
| 218 | steps: |
| 219 | - uses: actions/checkout@v4 |
| 220 | - uses: docker/setup-buildx-action@v3 |
| 221 | - uses: docker/login-action@v3 |
| 222 | with: |
| 223 | registry: ghcr.io |
| 224 | username: ${{ github.actor }} |
| 225 | password: ${{ secrets.GITHUB_TOKEN }} |
| 226 | - uses: docker/build-push-action@v5 |
| 227 | with: |
| 228 | push: true |
| 229 | tags: ghcr.io/${{ github.repository }}:${{ github.sha }} |
| 230 | cache-from: type=gha |
| 231 | cache-to: type=gha,mode=max |
| 232 | |
| 233 | deploy: |
| 234 | needs: build |
| 235 | runs-on: ubuntu-latest |
| 236 | if: github.ref == 'refs/heads/main' |
| 237 | environment: production |