介绍
Docker Compose 通常被归为本地开发,但它越来越多地用于中小型应用程序的单主机生产部署。 “Compose 不适用于生产”的常见批评忽略了一个关键点:对于许多工作负载,单个虚拟机上配置良好的 Compose 堆栈可以提供简单性和可靠性之间的适当平衡。
本指南涵盖了生产级 Compose 实践 - 通过适当的版本控制、CI/CD 集成和特定于生产的强化,将您的 compose 文件视为基础设施即代码。
1. 组合文件结构和版本控制
使用 Compose 规范(格式 3.8+)并采用多文件策略来分离关注点:
compose.yml # Base configuration (shared across environments)
compose.override.yml # Local development overrides (not used in production)
compose.prod.yml # Production-specific overrides
利用 YAML 锚点减少服务之间的重复:
x-logging: &logging
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
services:
app:
image: myapp:latest
logging: *logging
restart: unless-stopped
使用 --env-file 注入特定于环境的变量并避免硬编码秘密。优先使用 docker compose (v2),而不是已弃用的 docker-compose (v1)。
2. 服务依赖和健康检查
仅依靠 depends_on 不足以进行生产。使用 condition: service_healthy 确保服务在启动之前等待依赖项通过运行状况检查。
services:
postgres:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER"]
interval: 5s
timeout: 5s
retries: 5
start_period: 30s
app:
depends_on:
postgres:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/healthz"]
interval: 10s
timeout: 3s
retries: 3
这种级联健康检查模式 - Nginx → App → Redis → PostgreSQL - 确保每个服务仅在其依赖项真正准备就绪时启动。
3. 组网配置
使用带有 driver: bridge 的自定义网络进行服务隔离。避免使用默认的 bridge 网络,该网络缺乏通过 DNS 的服务发现。
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true
monitoring:
driver: bridge
services:
app:
networks:
frontend:
backend:
monitoring:
三网络拓扑提供了干净的分离:frontend 用于反向代理和应用程序,backend(内部)用于应用程序和数据库,monitoring 用于可观察性工具。使用网络别名在重新启动后实现稳定的 DNS 解析。
4. 资源约束和限制
生产容器必须有资源边界,以防止单个服务导致主机资源匮乏。
services:
app:
deploy:
resources:
limits:
cpus: '0.5'
memory: 256M
pids: 100
reservations:
cpus: '0.25'
memory: 128M
| 指令 | 目的 |
|---|---|
| 占位符_0 | 最大 CPU 核心数(例如 '0.5' = 半个核心) |
| 占位符_0 | OOM 终止前的最大内存 |
| 占位符_0 | 保证最低资源 |
| 占位符_0 | 文件描述符和进程限制(例如 nofile: 65536) |
对于 Node.js 应用程序,请将 --max-old-space-size 与内存限制对齐,以避免垃圾收集抖动。
5. 日志记录和可观察性
集中日志记录对于调试生产问题至关重要。配置 json-file 驱动程序进行轮换以防止磁盘耗尽:
x-logging: &logging
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
集中聚合的替代驱动因素:
| 司机 | 目的地 | 使用案例 |
|---|---|---|
| 占位符_0 | Fluentd → Elasticsearch | 全文搜索和分析 |
| 占位符_0 | 格雷洛格 | 结构化日志管理 |
| 占位符_0 | 亚马逊CloudWatch | AWS 原生部署 |
从应用程序输出结构化 JSON,以便 Docker 可以有效地转发它。使用 docker compose logs --tail 100 --follow 进行实时调试。
6. 秘密与环境管理
切勿在撰写文件中对机密进行硬编码。对于 Swarm 模式,使用静态加密并作为文件挂载的 Docker Secret:
secrets:
db_password:
file: ./secrets/db_password.txt
services:
app:
secrets:
- db_password
对于非 Swarm Compose,请使用 .env 文件(在 .gitignore 中列出),并使用 sops 或 age 进行加密。通过 $ 语法引用变量:
services:
app:
environment:
- DATABASE_URL=postgres://user:${DB_PASSWORD}@postgres:5432/myapp
定期轮换机密并使用 SERVICE_NAME_SECRET 等命名约定以保持清晰。
7. 滚动更新和零停机部署
使用 deploy.update_config 通过运行状况检查门控来编排滚动更新:
services:
app:
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
order: start-first
failure_action: rollback
rollback_config:
parallelism: 1
order: stop-first
| 参数 | 描述 |
|---|---|
| 占位符_0 | 一次更新的容器数量 |
| 占位符_0 | 更新组之间暂停 |
| 占位符_0 | start-first(蓝绿色)或 stop-first |
| 占位符_0 | pause、continue 或 rollback |
运行 docker compose up --detach --wait 进行精心策划的更新,等待运行状况检查通过,然后再考虑部署完成。
8. 反向代理集成
Traefik 是推荐用于 Compose 部署的反向代理。它通过 Docker 标签动态发现服务,并使用 Let’s Encrypt 自动执行 SSL 证书管理。
services:
traefik:
image: traefik:v3
command:
- "--providers.docker=true"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.le.acme.tlschallenge=true"
ports:
- "443:443"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
app:
labels:
- "traefik.http.routers.app.rule=Host(`example.com`)"
- "traefik.http.services.app.loadbalancer.server.port=3000"
替代方案:Nginx 需要手动上游定义和 SSL 终止配置。 Caddy 提供类似于 Traefik 的自动 HTTPS,但动态重新配置较少。
9. 监控与备份
为可观察性堆栈(cAdvisor + Prometheus + Grafana)定义一个单独的 monitoring.yml 撰写文件。这使得关注点分离——监控可以独立于应用程序进行更新。
对于数据库备份,通过 cron 安排 docker exec 转储:
0 3 * * * docker exec postgres pg_dump -U user mydb > /backups/db_$(date +\%Y\%m\%d).sql
使用 restart: unless-stopped 进行生产服务。与 restart: always 不同,这可以防止容器在手动 docker stop 之后重新启动。
结论
Docker Compose 对于适当规模的部署来说是可行的。将撰写文件视为代码、设计级联运行状况检查、设置资源限制、集中日志、正确管理机密并实施滚动更新。这些实践将 Compose 从一种方便的开发工具转变为一种强大的部署工具。
当扩展需求超出单个主机时,相同的 compose 文件提供了到 Docker Swarm 或 Kubernetes 的平滑迁移路径,使 Compose 成为容器编排的务实起点。

