为开发和生产设计可重用的 Docker Compose 配置
Docker Compose 是用于定义和运行多容器应用程序的标准工具。但许多团队陷入了为开发、登台和生产维护单独的 docker-compose.yml 文件的陷阱 - 导致重复、漂移和配置错误。
更好的方法使用组合文件覆盖、配置文件和环境变量来保持适应每个环境的单一事实来源。
基本 compose.yml 模式
从定义共享服务定义的单个 compose.yml 开始 - 在不同环境中保持不变的映像、命令、端口和环境。
# compose.yml
services:
app:
image: myapp:${APP_VERSION:-latest}
build:
context: .
target: ${BUILD_TARGET:-development}
ports:
- "${APP_PORT:-3000}:3000"
environment:
- NODE_ENV=${NODE_ENV:-development}
- DATABASE_URL=${DATABASE_URL}
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASS}
POSTGRES_DB: ${DB_NAME}
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"]
interval: 10s
timeout: 5s
retries: 5
volumes:
pgdata:
使用具有默认值 (${VAR:-default}) 的环境变量来保持基本文件的通用性。
使用 compose.override.yml 覆盖环境
Docker Compose 会自动读取 compose.override.yml(如果存在)。将此用于仅开发设置 - 切勿提交会影响生产的覆盖。
# compose.override.yml (excluded from production deployments)
services:
app:
build:
target: development
volumes:
- .:/app
- /app/node_modules
ports:
- "9229:9229" # debugger
environment:
- NODE_ENV=development
- DEBUG=app:*
command: npm run dev
db:
ports:
- "5432:5432" # expose for local tools
volumes:
- ./scripts/seed:/docker-entrypoint-initdb.d
对于生产,请使用单独的覆盖文件:
# compose.prod.yml
services:
app:
build:
target: production
restart: always
deploy:
resources:
limits:
cpus: '2'
memory: 1G
reservations:
cpus: '0.5'
memory: 256M
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
部署方式:docker compose -f compose.yml -f compose.prod.yml up -d
使用环境变体的配置文件
配置文件 (Docker Compose 2.0+) 让您可以根据环境有条件地启用服务。
services:
mailhog:
image: mailhog/mailhog
profiles: ["development", "staging"]
ports:
- "8025:8025"
redis:
image: redis:7-alpine
profiles: ["development", "staging", "production"]
redis-commander:
image: rediscommander/redis-commander
profiles: ["development"]
ports:
- "8081:8081"
运行 docker compose --profile development up 以仅启动与开发相关的服务。
健康检查和重启策略
始终为支持它们的每项服务定义健康检查。结合重启策略进行自我修复部署。
services:
app:
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "--spider", "http://localhost:3000/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 40s
worker:
restart: on-failure:5
depends_on:
app:
condition: service_healthy
depends_on.condition: service_healthy 确保工作线程仅在应用程序通过健康检查后启动。
资源限制和扩展
通过设置资源限制来防止失控的容器导致主机崩溃。
services:
app:
deploy:
resources:
limits:
cpus: '1'
memory: 512M
reservations:
cpus: '0.25'
memory: 128M
worker:
deploy:
mode: replicated
replicas: 3
resources:
limits:
cpus: '2'
memory: 1G
注意:deploy 设置适用于 Docker Swarm 和 Compose v3 堆栈。对于普通 docker compose,请使用 --compatibility 标志或特定于平台的限制。
保密管理
切勿在撰写文件中对机密进行硬编码。使用具有受限权限的 Docker 机密或环境文件。
# Using Docker secrets (Swarm mode)
secrets:
db_password:
file: ./secrets/db_password.txt
services:
app:
secrets:
- db_password
environment:
- DATABASE_URL=postgres://user:${DB_PASSWORD}@db:5432/myapp
对于非 Swarm 设置,请使用 .env 文件:
# .env (never committed to version control)
DB_USER=myapp
DB_PASS=s3cret!
DB_NAME=myapp
APP_PORT=3000
日志记录配置
集中日志记录可防止容器日志垃圾邮件填满您的磁盘。
services:
app:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# Production logging to a remote service
log-collector:
logging:
driver: "fluentd"
options:
fluentd-address: "localhost:24224"
tag: "docker.{{.Name}}"
结论
设计可重用的 Docker Compose 配置涉及关注点分离:用于共享定义的 基本 compose.yml、用于特定于环境的设置的 覆盖文件、用于条件服务的 配置文件,以及用于机密和配置的 环境变量。
这种分层方法消除了重复,减少了配置偏差,并使您的部署管道在开发、登台和生产过程中可预测。采用这些模式可以充满信心地发货。

