[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6G29DJM7FBYQAPCW6KCEMEE":3,"skill-same:01M6G29DJM7FBYQAPCW6KCEMEE":57},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":28,"linkOnly":29,"markdownContent":30,"markdownBody":31,"frontMatter":32,"refName":34,"commitSha":35,"skillDirectory":36,"forksCount":37,"repositoryHtmlUrl":38,"repositoryHomepageUrl":6,"ownerHtmlUrl":39,"ownerBlogUrl":40,"ownerDescription":41,"updatedAt":42,"install":43,"resources":56},"01M6G29DJM7FBYQAPCW6KCEMEE","deployment-patterns",null,"部署工作流、CI\u002FCD流水线模式、Docker容器化、健康检查、回滚策略以及Web应用程序的生产就绪检查清单。","oabdelmaksoud\u002FAgention","oabdelmaksoud","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F50699149?v=4","01M6D5CVVN778ZCDP1WHS816SP","Omar Abdelmaksoud","01M6D8A4TE76V3DCSH3D94VG1V",2,"MIT","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fdocs\u002Fzh-CN\u002Fskills\u002Fdeployment-patterns\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000011","运维与部署","SCENARIO","使用场景",[24,25,26,27],"deployment","patterns","deployment patterns","ci","2026-11-10 10:12:30",false,"---\nname: deployment-patterns\ndescription: 部署工作流、CI\u002FCD流水线模式、Docker容器化、健康检查、回滚策略以及Web应用程序的生产就绪检查清单。\norigin: ECC\n---\n\n# 部署模式\n\n生产环境部署工作流和 CI\u002FCD 最佳实践。\n\n## 何时启用\n\n* 设置 CI\u002FCD 流水线时\n* 将应用容器化（Docker）时\n* 规划部署策略（蓝绿、金丝雀、滚动）时\n* 实现健康检查和就绪探针时\n* 准备生产发布时\n* 配置环境特定设置时\n\n## 部署策略\n\n### 滚动部署（默认）\n\n逐步替换实例——在发布过程中，新旧版本同时运行。\n\n```\nInstance 1: v1 → v2  (update first)\nInstance 2: v1        (still running v1)\nInstance 3: v1        (still running v1)\n\nInstance 1: v2\nInstance 2: v1 → v2  (update second)\nInstance 3: v1\n\nInstance 1: v2\nInstance 2: v2\nInstance 3: v1 → v2  (update last)\n```\n\n**优点：** 零停机时间，渐进式发布\n**缺点：** 两个版本同时运行——需要向后兼容的更改\n**适用场景：** 标准部署，向后兼容的更改\n\n### 蓝绿部署\n\n运行两个相同的环境。原子化地切换流量。\n\n```\nBlue  (v1) ← traffic\nGreen (v2)   idle, running new version\n\n# After verification:\nBlue  (v1)   idle (becomes standby)\nGreen (v2) ← traffic\n```\n\n**优点：** 即时回滚（切换回蓝色环境），切换干净利落\n**缺点：** 部署期间需要双倍的基础设施\n**适用场景：** 关键服务，对问题零容忍\n\n### 金丝雀部署\n\n首先将一小部分流量路由到新版本。\n\n```\nv1: 95% of traffic\nv2:  5% of traffic  (canary)\n\n# If metrics look good:\nv1: 50% of traffic\nv2: 50% of traffic\n\n# Final:\nv2: 100% of traffic\n```\n\n**优点：** 在全量发布前，通过真实流量发现问题\n**缺点：** 需要流量分割基础设施和监控\n**适用场景：** 高流量服务，风险性更改，功能标志\n\n## Docker\n\n### 多阶段 Dockerfile (Node.js)\n\n```dockerfile\n# Stage 1: Install dependencies\nFROM node:22-alpine AS deps\nWORKDIR \u002Fapp\nCOPY package.json package-lock.json .\u002F\nRUN npm ci --production=false\n\n# Stage 2: Build\nFROM node:22-alpine AS builder\nWORKDIR \u002Fapp\nCOPY --from=deps \u002Fapp\u002Fnode_modules .\u002Fnode_modules\nCOPY . .\nRUN npm run build\nRUN npm prune --production\n\n# Stage 3: Production image\nFROM node:22-alpine AS runner\nWORKDIR \u002Fapp\n\nRUN addgroup -g 1001 -S appgroup && adduser -S appuser -u 1001\nUSER appuser\n\nCOPY --from=builder --chown=appuser:appgroup \u002Fapp\u002Fnode_modules .\u002Fnode_modules\nCOPY --from=builder --chown=appuser:appgroup \u002Fapp\u002Fdist .\u002Fdist\nCOPY --from=builder --chown=appuser:appgroup \u002Fapp\u002Fpackage.json .\u002F\n\nENV NODE_ENV=production\nEXPOSE 3000\n\nHEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\\n  CMD wget --no-verbose --tries=1 --spider http:\u002F\u002Flocalhost:3000\u002Fhealth || exit 1\n\nCMD [\"node\", \"dist\u002Fserver.js\"]\n```\n\n### 多阶段 Dockerfile (Go)\n\n```dockerfile\nFROM golang:1.22-alpine AS builder\nWORKDIR \u002Fapp\nCOPY go.mod go.sum .\u002F\nRUN go mod download\nCOPY . .\nRUN CGO_ENABLED=0 GOOS=linux go build -ldflags=\"-s -w\" -o \u002Fserver .\u002Fcmd\u002Fserver\n\nFROM alpine:3.19 AS runner\nRUN apk --no-cache add ca-certificates\nRUN adduser -D -u 1001 appuser\nUSER appuser\n\nCOPY --from=builder \u002Fserver \u002Fserver\n\nEXPOSE 8080\nHEALTHCHECK --interval=30s --timeout=3s CMD wget -qO- http:\u002F\u002Flocalhost:8080\u002Fhealth || exit 1\nCMD [\"\u002Fserver\"]\n```\n\n### 多阶段 Dockerfile (Python\u002FDjango)\n\n```dockerfile\nFROM python:3.12-slim AS builder\nWORKDIR \u002Fapp\nRUN pip install --no-cache-dir uv\nCOPY requirements.txt .\nRUN uv pip install --system --no-cache -r requirements.txt\n\nFROM python:3.12-slim AS runner\nWORKDIR \u002Fapp\n\nRUN useradd -r -u 1001 appuser\nUSER appuser\n\nCOPY --from=builder \u002Fusr\u002Flocal\u002Flib\u002Fpython3.12\u002Fsite-packages \u002Fusr\u002Flocal\u002Flib\u002Fpython3.12\u002Fsite-packages\nCOPY --from=builder \u002Fusr\u002Flocal\u002Fbin \u002Fusr\u002Flocal\u002Fbin\nCOPY . .\n\nENV PYTHONUNBUFFERED=1\nEXPOSE 8000\n\nHEALTHCHECK --interval=30s --timeout=3s CMD python -c \"import urllib.request; urllib.request.urlopen('http:\u002F\u002Flocalhost:8000\u002Fhealth\u002F')\" || exit 1\nCMD [\"gunicorn\", \"config.wsgi:application\", \"--bind\", \"0.0.0.0:8000\", \"--workers\", \"4\"]\n```\n\n### Docker 最佳实践\n\n```\n# GOOD practices\n- Use specific version tags (node:22-alpine, not node:latest)\n- Multi-stage builds to minimize image size\n- Run as non-root user\n- Copy dependency files first (layer caching)\n- Use .dockerignore to exclude node_modules, .git, tests\n- Add HEALTHCHECK instruction\n- Set resource limits in docker-compose or k8s\n\n# BAD practices\n- Running as root\n- Using :latest tags\n- Copying entire repo in one COPY layer\n- Installing dev dependencies in production image\n- Storing secrets in image (use env vars or secrets manager)\n```\n\n## CI\u002FCD 流水线\n\n### GitHub Actions (标准流水线)\n\n```yaml\nname: CI\u002FCD\n\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: actions\u002Fsetup-node@v4\n        with:\n          node-version: 22\n          cache: npm\n      - run: npm ci\n      - run: npm run lint\n      - run: npm run typecheck\n      - run: npm test -- --coverage\n      - uses: actions\u002Fupload-artifact@v4\n        if: always()\n        with:\n          name: coverage\n          path: coverage\u002F\n\n  build:\n    needs: test\n    runs-on: ubuntu-latest\n    if: github.ref == 'refs\u002Fheads\u002Fmain'\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: docker\u002Fsetup-buildx-action@v3\n      - uses: docker\u002Flogin-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      - uses: docker\u002Fbuild-push-action@v5\n        with:\n          push: true\n          tags: ghcr.io\u002F${{ github.repository }}:${{ github.sha }}\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n\n  deploy:\n    needs: build\n    runs-on: ubuntu-latest\n    if: github.ref == 'refs\u002Fheads\u002Fmain'\n    environment: production\n    steps:\n      - name: Deploy to production\n        run: |\n          # Platform-specific deployment command\n          # Railway: railway up\n          # Vercel: vercel --prod\n          # K8s: kubectl set image deployment\u002Fapp app=ghcr.io\u002F${{ github.repository }}:${{ github.sha }}\n          echo \"Deploying ${{ github.sha }}\"\n```\n\n### 流水线阶段\n\n```\nPR opened:\n  lint → typecheck → unit tests → integration tests → preview deploy\n\nMerged to main:\n  lint → typecheck → unit tests → integration tests → build image → deploy staging → smoke tests → deploy production\n```\n\n## 健康检查\n\n### 健康检查端点\n\n```typescript\n\u002F\u002F Simple health check\napp.get(\"\u002Fhealth\", (req, res) => {\n  res.status(200).json({ status: \"ok\" });\n});\n\n\u002F\u002F Detailed health check (for internal monitoring)\napp.get(\"\u002Fhealth\u002Fdetailed\", async (req, res) => {\n  const checks = {\n    database: await checkDatabase(),\n    redis: await checkRedis(),\n    externalApi: await checkExternalApi(),\n  };\n\n  const allHealthy = Object.values(checks).every(c => c.status === \"ok\");\n\n  res.status(allHealthy ? 200 : 503).json({\n    status: allHealthy ? \"ok\" : \"degraded\",\n    timestamp: new Date().toISOString(),\n    version: process.env.APP_VERSION || \"unknown\",\n    uptime: process.uptime(),\n    checks,\n  });\n});\n\nasync function checkDatabase(): Promise\u003CHealthCheck> {\n  try {\n    await db.query(\"SELECT 1\");\n    return { status: \"ok\", latency_ms: 2 };\n  } catch (err) {\n    return { status: \"error\", message: \"Database unreachable\" };\n  }\n}\n```\n\n### Kubernetes 探针\n\n```yaml\nlivenessProbe:\n  httpGet:\n    path: \u002Fhealth\n    port: 3000\n  initialDelaySeconds: 10\n  periodSeconds: 30\n  failureThreshold: 3\n\nreadinessProbe:\n  httpGet:\n    path: \u002Fhealth\n    port: 3000\n  initialDelaySeconds: 5\n  periodSeconds: 10\n  failureThreshold: 2\n\nstartupProbe:\n  httpGet:\n    path: \u002Fhealth\n    port: 3000\n  initialDelaySeconds: 0\n  periodSeconds: 5\n  failureThreshold: 30    # 30 * 5s = 150s max startup time\n```\n\n## 环境配置\n\n### 十二要素应用模式\n\n```bash\n# All config via environment variables — never in code\nDATABASE_URL=postgres:\u002F\u002Fuser:pass@host:5432\u002Fdb\nREDIS_URL=redis:\u002F\u002Fhost:6379\u002F0\nAPI_KEY=${API_KEY}           # injected by secrets manager\nLOG_LEVEL=info\nPORT=3000\n\n# Environment-specific behavior\nNODE_ENV=production          # or staging, development\nAPP_ENV=production           # explicit app environment\n```\n\n### 配置验证\n\n```typescript\nimport { z } from \"zod\";\n\nconst envSchema = z.object({\n  NODE_ENV: z.enum([\"development\", \"staging\", \"production\"]),\n  PORT: z.coerce.number().default(3000),\n  DATABASE_URL: z.string().url(),\n  REDIS_URL: z.string().url(),\n  JWT_SECRET: z.string().min(32),\n  LOG_LEVEL: z.enum([\"debug\", \"info\", \"warn\", \"error\"]).default(\"info\"),\n});\n\n\u002F\u002F Validate at startup — fail fast if config is wrong\nexport const env = envSchema.parse(process.env);\n```\n\n## 回滚策略\n\n### 即时回滚\n\n```bash\n# Docker\u002FKubernetes: point to previous image\nkubectl rollout undo deployment\u002Fapp\n\n# Vercel: promote previous deployment\nvercel rollback\n\n# Railway: redeploy previous commit\nrailway up --commit \u003Cprevious-sha>\n\n# Database: rollback migration (if reversible)\nnpx prisma migrate resolve --rolled-back \u003Cmigration-name>\n```\n\n### 回滚检查清单\n\n* \\[ ] 之前的镜像\u002F制品可用且已标记\n* \\[ ] 数据库迁移向后兼容（无破坏性更改）\n* \\[ ] 功能标志可以在不部署的情况下禁用新功能\n* \\[ ] 监控警报已配置，用于错误率飙升\n* \\[ ] 在生产发布前，回滚已在预演环境测试\n\n## 生产就绪检查清单\n\n在任何生产部署之前：\n\n### 应用\n\n* \\[ ] 所有测试通过（单元、集成、端到端）\n* \\[ ] 代码或配置文件中没有硬编码的密钥\n* \\[ ] 错误处理覆盖所有边缘情况\n* \\[ ] 日志是结构化的（JSON）且不包含 PII\n* \\[ ] 健康检查端点返回有意义的状态\n\n### 基础设施\n\n* \\[ ] Docker 镜像可重复构建（版本已固定）\n* \\[ ] 环境变量已记录并在启动时验证\n* \\[ ] 资源限制已设置（CPU、内存）\n* \\[ ] 水平伸缩已配置（最小\u002F最大实例数）\n* \\[ ] 所有端点均已启用 SSL\u002FTLS\n\n### 监控\n\n* \\[ ] 应用指标已导出（请求率、延迟、错误）\n* \\[ ] 已配置错误率超过阈值的警报\n* \\[ ] 日志聚合已设置（结构化日志，可搜索）\n* \\[ ] 健康端点有正常运行时间监控\n\n### 安全\n\n* \\[ ] 依赖项已扫描 CVE\n* \\[ ] CORS 仅配置允许的来源\n* \\[ ] 公共端点已启用速率限制\n* \\[ ] 身份验证和授权已验证\n* \\[ ] 安全头已设置（CSP、HSTS、X-Frame-Options）\n\n### 运维\n\n* \\[ ] 回滚计划已记录并测试\n* \\[ ] 数据库迁移已针对生产规模的数据进行测试\n* \\[ ] 常见故障场景的应急预案\n* \\[ ] 待命轮换和升级路径已定义\n","# 部署模式\n\n生产环境部署工作流和 CI\u002FCD 最佳实践。\n\n## 何时启用\n\n* 设置 CI\u002FCD 流水线时\n* 将应用容器化（Docker）时\n* 规划部署策略（蓝绿、金丝雀、滚动）时\n* 实现健康检查和就绪探针时\n* 准备生产发布时\n* 配置环境特定设置时\n\n## 部署策略\n\n### 滚动部署（默认）\n\n逐步替换实例——在发布过程中，新旧版本同时运行。\n\n```\nInstance 1: v1 → v2  (update first)\nInstance 2: v1        (still running v1)\nInstance 3: v1        (still running v1)\n\nInstance 1: v2\nInstance 2: v1 → v2  (update second)\nInstance 3: v1\n\nInstance 1: v2\nInstance 2: v2\nInstance 3: v1 → v2  (update last)\n```\n\n**优点：** 零停机时间，渐进式发布\n**缺点：** 两个版本同时运行——需要向后兼容的更改\n**适用场景：** 标准部署，向后兼容的更改\n\n### 蓝绿部署\n\n运行两个相同的环境。原子化地切换流量。\n\n```\nBlue  (v1) ← traffic\nGreen (v2)   idle, running new version\n\n# After verification:\nBlue  (v1)   idle (becomes standby)\nGreen (v2) ← traffic\n```\n\n**优点：** 即时回滚（切换回蓝色环境），切换干净利落\n**缺点：** 部署期间需要双倍的基础设施\n**适用场景：** 关键服务，对问题零容忍\n\n### 金丝雀部署\n\n首先将一小部分流量路由到新版本。\n\n```\nv1: 95% of traffic\nv2:  5% of traffic  (canary)\n\n# If metrics look good:\nv1: 50% of traffic\nv2: 50% of traffic\n\n# Final:\nv2: 100% of traffic\n```\n\n**优点：** 在全量发布前，通过真实流量发现问题\n**缺点：** 需要流量分割基础设施和监控\n**适用场景：** 高流量服务，风险性更改，功能标志\n\n## Docker\n\n### 多阶段 Dockerfile (Node.js)\n\n```dockerfile\n# Stage 1: Install dependencies\nFROM node:22-alpine AS deps\nWORKDIR \u002Fapp\nCOPY package.json package-lock.json .\u002F\nRUN npm ci --production=false\n\n# Stage 2: Build\nFROM node:22-alpine AS builder\nWORKDIR \u002Fapp\nCOPY --from=deps \u002Fapp\u002Fnode_modules .\u002Fnode_modules\nCOPY . .\nRUN npm run build\nRUN npm prune --production\n\n# Stage 3: Production image\nFROM node:22-alpine AS runner\nWORKDIR \u002Fapp\n\nRUN addgroup -g 1001 -S appgroup && adduser -S appuser -u 1001\nUSER appuser\n\nCOPY --from=builder --chown=appuser:appgroup \u002Fapp\u002Fnode_modules .\u002Fnode_modules\nCOPY --from=builder --chown=appuser:appgroup \u002Fapp\u002Fdist .\u002Fdist\nCOPY --from=builder --chown=appuser:appgroup \u002Fapp\u002Fpackage.json .\u002F\n\nENV NODE_ENV=production\nEXPOSE 3000\n\nHEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\\n  CMD wget --no-verbose --tries=1 --spider http:\u002F\u002Flocalhost:3000\u002Fhealth || exit 1\n\nCMD [\"node\", \"dist\u002Fserver.js\"]\n```\n\n### 多阶段 Dockerfile (Go)\n\n```dockerfile\nFROM golang:1.22-alpine AS builder\nWORKDIR \u002Fapp\nCOPY go.mod go.sum .\u002F\nRUN go mod download\nCOPY . .\nRUN CGO_ENABLED=0 GOOS=linux go build -ldflags=\"-s -w\" -o \u002Fserver .\u002Fcmd\u002Fserver\n\nFROM alpine:3.19 AS runner\nRUN apk --no-cache add ca-certificates\nRUN adduser -D -u 1001 appuser\nUSER appuser\n\nCOPY --from=builder \u002Fserver \u002Fserver\n\nEXPOSE 8080\nHEALTHCHECK --interval=30s --timeout=3s CMD wget -qO- http:\u002F\u002Flocalhost:8080\u002Fhealth || exit 1\nCMD [\"\u002Fserver\"]\n```\n\n### 多阶段 Dockerfile (Python\u002FDjango)\n\n```dockerfile\nFROM python:3.12-slim AS builder\nWORKDIR \u002Fapp\nRUN pip install --no-cache-dir uv\nCOPY requirements.txt .\nRUN uv pip install --system --no-cache -r requirements.txt\n\nFROM python:3.12-slim AS runner\nWORKDIR \u002Fapp\n\nRUN useradd -r -u 1001 appuser\nUSER appuser\n\nCOPY --from=builder \u002Fusr\u002Flocal\u002Flib\u002Fpython3.12\u002Fsite-packages \u002Fusr\u002Flocal\u002Flib\u002Fpython3.12\u002Fsite-packages\nCOPY --from=builder \u002Fusr\u002Flocal\u002Fbin \u002Fusr\u002Flocal\u002Fbin\nCOPY . .\n\nENV PYTHONUNBUFFERED=1\nEXPOSE 8000\n\nHEALTHCHECK --interval=30s --timeout=3s CMD python -c \"import urllib.request; urllib.request.urlopen('http:\u002F\u002Flocalhost:8000\u002Fhealth\u002F')\" || exit 1\nCMD [\"gunicorn\", \"config.wsgi:application\", \"--bind\", \"0.0.0.0:8000\", \"--workers\", \"4\"]\n```\n\n### Docker 最佳实践\n\n```\n# GOOD practices\n- Use specific version tags (node:22-alpine, not node:latest)\n- Multi-stage builds to minimize image size\n- Run as non-root user\n- Copy dependency files first (layer caching)\n- Use .dockerignore to exclude node_modules, .git, tests\n- Add HEALTHCHECK instruction\n- Set resource limits in docker-compose or k8s\n\n# BAD practices\n- Running as root\n- Using :latest tags\n- Copying entire repo in one COPY layer\n- Installing dev dependencies in production image\n- Storing secrets in image (use env vars or secrets manager)\n```\n\n## CI\u002FCD 流水线\n\n### GitHub Actions (标准流水线)\n\n```yaml\nname: CI\u002FCD\n\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: actions\u002Fsetup-node@v4\n        with:\n          node-version: 22\n          cache: npm\n      - run: npm ci\n      - run: npm run lint\n      - run: npm run typecheck\n      - run: npm test -- --coverage\n      - uses: actions\u002Fupload-artifact@v4\n        if: always()\n        with:\n          name: coverage\n          path: coverage\u002F\n\n  build:\n    needs: test\n    runs-on: ubuntu-latest\n    if: github.ref == 'refs\u002Fheads\u002Fmain'\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: docker\u002Fsetup-buildx-action@v3\n      - uses: docker\u002Flogin-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      - uses: docker\u002Fbuild-push-action@v5\n        with:\n          push: true\n          tags: ghcr.io\u002F${{ github.repository }}:${{ github.sha }}\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n\n  deploy:\n    needs: build\n    runs-on: ubuntu-latest\n    if: github.ref == 'refs\u002Fheads\u002Fmain'\n    environment: production\n    steps:\n      - name: Deploy to production\n        run: |\n          # Platform-specific deployment command\n          # Railway: railway up\n          # Vercel: vercel --prod\n          # K8s: kubectl set image deployment\u002Fapp app=ghcr.io\u002F${{ github.repository }}:${{ github.sha }}\n          echo \"Deploying ${{ github.sha }}\"\n```\n\n### 流水线阶段\n\n```\nPR opened:\n  lint → typecheck → unit tests → integration tests → preview deploy\n\nMerged to main:\n  lint → typecheck → unit tests → integration tests → build image → deploy staging → smoke tests → deploy production\n```\n\n## 健康检查\n\n### 健康检查端点\n\n```typescript\n\u002F\u002F Simple health check\napp.get(\"\u002Fhealth\", (req, res) => {\n  res.status(200).json({ status: \"ok\" });\n});\n\n\u002F\u002F Detailed health check (for internal monitoring)\napp.get(\"\u002Fhealth\u002Fdetailed\", async (req, res) => {\n  const checks = {\n    database: await checkDatabase(),\n    redis: await checkRedis(),\n    externalApi: await checkExternalApi(),\n  };\n\n  const allHealthy = Object.values(checks).every(c => c.status === \"ok\");\n\n  res.status(allHealthy ? 200 : 503).json({\n    status: allHealthy ? \"ok\" : \"degraded\",\n    timestamp: new Date().toISOString(),\n    version: process.env.APP_VERSION || \"unknown\",\n    uptime: process.uptime(),\n    checks,\n  });\n});\n\nasync function checkDatabase(): Promise\u003CHealthCheck> {\n  try {\n    await db.query(\"SELECT 1\");\n    return { status: \"ok\", latency_ms: 2 };\n  } catch (err) {\n    return { status: \"error\", message: \"Database unreachable\" };\n  }\n}\n```\n\n### Kubernetes 探针\n\n```yaml\nlivenessProbe:\n  httpGet:\n    path: \u002Fhealth\n    port: 3000\n  initialDelaySeconds: 10\n  periodSeconds: 30\n  failureThreshold: 3\n\nreadinessProbe:\n  httpGet:\n    path: \u002Fhealth\n    port: 3000\n  initialDelaySeconds: 5\n  periodSeconds: 10\n  failureThreshold: 2\n\nstartupProbe:\n  httpGet:\n    path: \u002Fhealth\n    port: 3000\n  initialDelaySeconds: 0\n  periodSeconds: 5\n  failureThreshold: 30    # 30 * 5s = 150s max startup time\n```\n\n## 环境配置\n\n### 十二要素应用模式\n\n```bash\n# All config via environment variables — never in code\nDATABASE_URL=postgres:\u002F\u002Fuser:pass@host:5432\u002Fdb\nREDIS_URL=redis:\u002F\u002Fhost:6379\u002F0\nAPI_KEY=${API_KEY}           # injected by secrets manager\nLOG_LEVEL=info\nPORT=3000\n\n# Environment-specific behavior\nNODE_ENV=production          # or staging, development\nAPP_ENV=production           # explicit app environment\n```\n\n### 配置验证\n\n```typescript\nimport { z } from \"zod\";\n\nconst envSchema = z.object({\n  NODE_ENV: z.enum([\"development\", \"staging\", \"production\"]),\n  PORT: z.coerce.number().default(3000),\n  DATABASE_URL: z.string().url(),\n  REDIS_URL: z.string().url(),\n  JWT_SECRET: z.string().min(32),\n  LOG_LEVEL: z.enum([\"debug\", \"info\", \"warn\", \"error\"]).default(\"info\"),\n});\n\n\u002F\u002F Validate at startup — fail fast if config is wrong\nexport const env = envSchema.parse(process.env);\n```\n\n## 回滚策略\n\n### 即时回滚\n\n```bash\n# Docker\u002FKubernetes: point to previous image\nkubectl rollout undo deployment\u002Fapp\n\n# Vercel: promote previous deployment\nvercel rollback\n\n# Railway: redeploy previous commit\nrailway up --commit \u003Cprevious-sha>\n\n# Database: rollback migration (if reversible)\nnpx prisma migrate resolve --rolled-back \u003Cmigration-name>\n```\n\n### 回滚检查清单\n\n* \\[ ] 之前的镜像\u002F制品可用且已标记\n* \\[ ] 数据库迁移向后兼容（无破坏性更改）\n* \\[ ] 功能标志可以在不部署的情况下禁用新功能\n* \\[ ] 监控警报已配置，用于错误率飙升\n* \\[ ] 在生产发布前，回滚已在预演环境测试\n\n## 生产就绪检查清单\n\n在任何生产部署之前：\n\n### 应用\n\n* \\[ ] 所有测试通过（单元、集成、端到端）\n* \\[ ] 代码或配置文件中没有硬编码的密钥\n* \\[ ] 错误处理覆盖所有边缘情况\n* \\[ ] 日志是结构化的（JSON）且不包含 PII\n* \\[ ] 健康检查端点返回有意义的状态\n\n### 基础设施\n\n* \\[ ] Docker 镜像可重复构建（版本已固定）\n* \\[ ] 环境变量已记录并在启动时验证\n* \\[ ] 资源限制已设置（CPU、内存）\n* \\[ ] 水平伸缩已配置（最小\u002F最大实例数）\n* \\[ ] 所有端点均已启用 SSL\u002FTLS\n\n### 监控\n\n* \\[ ] 应用指标已导出（请求率、延迟、错误）\n* \\[ ] 已配置错误率超过阈值的警报\n* \\[ ] 日志聚合已设置（结构化日志，可搜索）\n* \\[ ] 健康端点有正常运行时间监控\n\n### 安全\n\n* \\[ ] 依赖项已扫描 CVE\n* \\[ ] CORS 仅配置允许的来源\n* \\[ ] 公共端点已启用速率限制\n* \\[ ] 身份验证和授权已验证\n* \\[ ] 安全头已设置（CSP、HSTS、X-Frame-Options）\n\n### 运维\n\n* \\[ ] 回滚计划已记录并测试\n* \\[ ] 数据库迁移已针对生产规模的数据进行测试\n* \\[ ] 常见故障场景的应急预案\n* \\[ ] 待命轮换和升级路径已定义\n",{"name":5,"origin":33,"description":7},"ECC","main","a318f48de3c5718e8ea2e9f6fae7790e8a759e85","upstream-sync\u002Fwork\u002Fecc\u002Fdocs\u002Fzh-CN\u002Fskills\u002Fdeployment-patterns",0,"https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fo-abdelmaksoud\u002F","Full-Stack Engineer | AI Systems Architect | Building autonomous multi-agent systems","2026-03-08 21:23:03",{"source":8,"skillName":5,"commands":44,"prompt":54,"zipAvailable":55},[45,48,51],{"tool":46,"command":47},"npx","npx skills add oabdelmaksoud\u002FAgention --skill deployment-patterns",{"tool":49,"command":50},"bunx","bunx skills add oabdelmaksoud\u002FAgention --skill deployment-patterns",{"tool":52,"command":53},"pnpm","pnpm dlx skills add oabdelmaksoud\u002FAgention --skill deployment-patterns","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fdocs\u002Fzh-CN\u002Fskills\u002Fdeployment-patterns\u002FSKILL.md",true,[],[58,80,94,127,152,172],{"skillNo":59,"name":60,"nameZh":6,"description":61,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":62,"categories":63,"keywords":67,"publishedAt":28},"01M6G2QFCBNBYAJF2KTK85G9A6","visa-doc-translate","Translate visa application documents (images) to English and create a bilingual PDF with original and translation","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fvisa-doc-translate\u002FSKILL.md",[64],{"categoryNo":65,"categoryName":66,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000002","文档处理",[68,69,70,71,72,73,74,75,76,77,78,79],"translate","doc","visa doc translate","bilingual","with","english","application","PDF","translation","documents","create","images",{"skillNo":81,"name":82,"nameZh":6,"description":83,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":84,"categories":85,"keywords":86,"publishedAt":28},"01M6G2QB09TSK6BY4ME5X20EVQ","verification-loop","A comprehensive verification system for Claude Code sessions.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fverification-loop\u002FSKILL.md",[],[87,88,89,90,91,92,93],"verification","loop","verification loop","sessions","code","claude code sessions","system",{"skillNo":95,"name":96,"nameZh":6,"description":97,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":98,"categories":99,"keywords":111,"publishedAt":28},"01M6G2Q6V2F7G03VAAF27FXPJR","tdd-workflow","Use this skill when writing new features, fixing bugs, or refactoring code. Enforces test-driven development with 80%+ coverage including unit, integration, and E2E tests.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Ftdd-workflow\u002FSKILL.md",[100,103,106],{"categoryNo":101,"categoryName":102,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":104,"categoryName":105,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",{"categoryNo":107,"categoryName":108,"taxonomyType":109,"taxonomyTypeDesc":110},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[112,113,114,115,116,117,118,119,120,91,121,122,123,124,72,125,126],"workflow","tdd","tdd workflow","use","unit","coverage","refactoring","e2e","integration","development","e2e tests","tests","driven","test","writing",{"skillNo":128,"name":129,"nameZh":6,"description":130,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":131,"categories":132,"keywords":133,"publishedAt":28},"01M6G2Q359YJRWAR2PFCEQAXF3","swiftui-patterns","SwiftUI architecture patterns, state management with @Observable, view composition, navigation, performance optimization, and modern iOS\u002FmacOS UI best practices.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fswiftui-patterns\u002FSKILL.md",[],[25,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,72],"swiftui","swiftui patterns","architecture","macos","performance","state management","best practices","state","ui","Optimization","ios","architecture patterns","Composition","performance optimization","view","management","swiftui architecture","navigation",{"skillNo":153,"name":154,"nameZh":6,"description":155,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":156,"categories":157,"keywords":159,"publishedAt":28},"01M6G2PY8B2FWZTWPZ84H83Y7C","swift-protocol-di-testing","Protocol-based dependency injection for testable Swift code — mock file system, network, and external APIs using focused protocols and Swift Testing.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fswift-protocol-di-testing\u002FSKILL.md",[158],{"categoryNo":101,"categoryName":102,"taxonomyType":21,"taxonomyTypeDesc":22},[160,161,162,163,91,164,165,166,167,93,168,169,170,171],"swift protocol di testing","protocol","swift","testing","protocols","file","network","injection","dependency","swift testing","dependency injection","mock",{"skillNo":173,"name":174,"nameZh":6,"description":175,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":176,"categories":177,"keywords":178,"publishedAt":28},"01M6G2PSCN2GXV9FFZDRRRWVB6","swift-concurrency-6-2","Swift 6.2 Approachable Concurrency — single-threaded by default, @concurrent for explicit background offloading, isolated conformances for main actor types.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fswift-concurrency-6-2\u002FSKILL.md",[],[179,180,181,162,182,34,183],"concurrency","swift concurrency","swift concurrency 6 2","default","types"]