Docker Compose 生产实践
大约 10 分钟约 2861 字
Docker Compose 生产实践
简介
Docker Compose 是 Docker 官方提供的容器编排工具,它通过 YAML 配置文件定义和运行多容器应用。虽然 Docker Compose 主要面向开发和测试环境,但通过合理的配置优化,它同样可以胜任中小规模的生产环境部署。本文将深入探讨 Docker Compose 在生产环境中的最佳实践,包括健康检查、资源限制、日志管理和滚动更新策略,帮助运维团队构建稳定可靠的容器化应用。
特点
健康检查配置
健康检查是生产环境容器管理的关键机制,确保只有健康的容器才能接收流量。
# docker-compose.yml - 完整生产配置
version: "3.9"
services:
# Web 应用服务
webapp:
image: myregistry.com/webapp:v2.1.0
container_name: webapp
restart: always
ports:
- "8080:8080"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/healthz"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
environment:
- NODE_ENV=production
- DB_HOST=postgres
- DB_PORT=5432
- DB_NAME=appdb
- REDIS_URL=redis://redis:6379
- LOG_LEVEL=info
env_file:
- .env.secrets
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
networks:
- frontend
- backend
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 30s
failure_action: rollback
order: start-first
rollback_config:
parallelism: 0
order: stop-first
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 5
window: 120s # PostgreSQL 数据库
postgres:
image: postgres:16-alpine
container_name: postgres
restart: always
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-appuser} -d ${DB_NAME:-appdb}"]
interval: 15s
timeout: 5s
retries: 5
start_period: 30s
environment:
POSTGRES_USER: ${DB_USER:-appuser}
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: ${DB_NAME:-appdb}
POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --lc-collate=C --lc-ctype=C"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./init-db.sql:/docker-entrypoint-initdb.d/init.sql:ro
networks:
- backend
deploy:
resources:
limits:
cpus: "2.0"
memory: 2G
reservations:
cpus: "0.5"
memory: 512M
# Redis 缓存
redis:
image: redis:7-alpine
container_name: redis
restart: always
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 3
command: >
redis-server
--maxmemory 512mb
--maxmemory-policy allkeys-lru
--appendonly yes
--appendfsync everysec
--save 900 1
--save 300 10
volumes:
- redis_data:/data
networks:
- backend资源限制
生产环境中必须对容器资源进行限制,避免单个服务故障影响整个系统。
# Nginx 反向代理
nginx:
image: nginx:1.25-alpine
container_name: nginx
restart: always
ports:
- "80:80"
- "443:443"
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/health"]
interval: 30s
timeout: 5s
retries: 3
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./nginx/ssl:/etc/nginx/ssl:ro
- nginx_logs:/var/log/nginx
depends_on:
webapp:
condition: service_healthy
networks:
- frontend
deploy:
resources:
limits:
cpus: "1.0"
memory: 512M
reservations:
cpus: "0.25"
memory: 128M
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "5"
tag: "nginx"
# 后端 Worker 服务
worker:
image: myregistry.com/worker:v2.1.0
container_name: worker
restart: always
healthcheck:
test: ["CMD", "node", "healthcheck.js"]
interval: 60s
timeout: 15s
retries: 3
start_period: 60s
environment:
- NODE_ENV=production
- DB_HOST=postgres
- REDIS_URL=redis://redis:6379
- WORKER_CONCURRENCY=10
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
networks:
- backend
deploy:
replicas: 2
resources:
limits:
cpus: "1.5"
memory: 1G
reservations:
cpus: "0.5"
memory: 256M日志管理
合理的日志配置对于生产环境的故障排查和监控至关重要。
# 日志采集服务 (Filebeat)
filebeat:
image: elastic/filebeat:8.11.0
container_name: filebeat
restart: always
user: root
volumes:
- ./filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
- nginx_logs:/var/log/nginx:ro
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- ELASTICSEARCH_HOST=${ES_HOST:-elasticsearch:9200}
networks:
- backend
deploy:
resources:
limits:
cpus: "0.5"
memory: 256M
# Prometheus 监控
prometheus:
image: prom/prometheus:v2.48.0
container_name: prometheus
restart: always
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:9090/-/healthy"]
interval: 30s
timeout: 5s
retries: 3
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- ./prometheus/rules:/etc/prometheus/rules:ro
- prometheus_data:/prometheus
command:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--storage.tsdb.retention.time=30d"
- "--storage.tsdb.retention.size=10GB"
- "--web.enable-lifecycle"
networks:
- backend
deploy:
resources:
limits:
cpus: "1.0"
memory: 1G
reservations:
cpus: "0.25"
memory: 256M
logging:
driver: "json-file"
options:
max-size: "20m"
max-file: "3"全局配置与网络
# 网络定义
networks:
frontend:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
driver_opts:
com.docker.network.bridge.name: br_frontend
backend:
driver: bridge
internal: true
ipam:
config:
- subnet: 172.21.0.0/16
# 数据卷定义
volumes:
postgres_data:
driver: local
driver_opts:
type: none
o: bind
device: /data/postgres
redis_data:
driver: local
driver_opts:
type: none
o: bind
device: /data/redis
nginx_logs:
driver: local
prometheus_data:
driver: local生产运维命令
# 启动所有服务
docker compose up -d
# 查看服务状态和健康检查结果
docker compose ps
docker compose ps --format json
# 查看资源使用情况
docker stats --no-stream
# 滚动更新 Web 应用
docker compose pull webapp
docker compose up -d --no-deps --build webapp
# 查看日志
docker compose logs -f --tail=100 webapp
docker compose logs --since 1h nginx
# 扩容 Worker 服务
docker compose up -d --scale worker=5
# 重启特定服务(保留容器)
docker compose restart webapp
# 优雅停止并保留数据
docker compose down --timeout 60
# 完全清理(包括数据卷)
docker compose down -v --rmi allDockerfile 生产优化
与 Compose 配合的 Dockerfile 同样需要针对生产环境优化。
# 多阶段构建 — 减小最终镜像体积
# 阶段 1:构建
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["MyApp.csproj", "./"]
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /app --no-restore
# 阶段 2:运行时
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine AS runtime
WORKDIR /app
# 安全:使用非 root 用户
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
# 健康检查
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/healthz || exit 1
COPY --from=build /app .
# 设置环境变量
ENV ASPNETCORE_URLS=http://+:8080
ENV ASPNETCORE_ENVIRONMENT=Production
ENV DOTNET_EnableDiagnostics=0
EXPOSE 8080
ENTRYPOINT ["dotnet", "MyApp.dll"]# Node.js 多阶段构建示例
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
FROM node:20-alpine
WORKDIR /app
RUN addgroup -S node && adduser -S node -G node
USER node
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
COPY --from=build /app/package.json ./
HEALTHCHECK --interval=30s --timeout=5s \
CMD wget --spider http://localhost:3000/health || exit 1
EXPOSE 3000
CMD ["node", "dist/main.js"]镜像安全与优化检查清单
# 1. 镜像体积分析
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
docker history myapp:latest --no-trunc --format "table {{.CreatedBy}}\t{{.Size}}"
# 2. 安全扫描
docker scout cves myapp:latest
# 或使用 Trivy
trivy image myapp:latest
# 3. 检查镜像层
docker inspect myapp:latest --format '{{json .RootFS.Layers}}' | python3 -m json.tool
# 4. 常见优化措施:
# - 使用 alpine 基础镜像
# - 多阶段构建分离编译和运行环境
# - 合并 RUN 指令减少层数
# - 使用 .dockerignore 排除不必要文件
# - 不在镜像中包含源代码或构建工具
# - 固定基础镜像版本(不用 latest)Compose 环境管理
多环境配置
# docker-compose.yml — 基础配置(所有环境共用)
services:
webapp:
build: .
environment:
- NODE_ENV=${NODE_ENV:-development}
ports:
- "${WEB_PORT:-3000}:3000"# docker-compose.override.yml — 开发环境(自动加载)
# Docker Compose 会自动合并 docker-compose.yml 和 docker-compose.override.yml
services:
webapp:
build:
context: .
target: development
volumes:
- ./src:/app/src:ro # 挂载源代码实现热重载
- ./tests:/app/tests:ro
environment:
- NODE_ENV=development
- LOG_LEVEL=debug
ports:
- "3000:3000"
- "9229:9229" # Node.js 调试端口# docker-compose.prod.yml — 生产环境(需手动指定)
# docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
services:
webapp:
image: myregistry.com/webapp:${VERSION:-latest}
restart: always
deploy:
replicas: 3
resources:
limits:
cpus: "1.0"
memory: 512M
environment:
- NODE_ENV=production
- LOG_LEVEL=warn
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "5"# docker-compose.staging.yml — 预发布环境
services:
webapp:
image: myregistry.com/webapp:${VERSION}
restart: on-failure
deploy:
replicas: 1
resources:
limits:
cpus: "0.5"
memory: 256M
environment:
- NODE_ENV=staging
- LOG_LEVEL=info环境变量管理最佳实践
# .env — 公共配置(纳入版本控制)
COMPOSE_PROJECT_NAME=myapp
WEB_PORT=3000
DB_NAME=appdb
REDIS_PORT=6379
# .env.secrets — 敏感配置(不纳入版本控制,加入 .gitignore)
DB_PASSWORD=your_secure_password
JWT_SECRET=your_jwt_secret_key
API_KEY=your_api_key
# 使用方式:
# 1. 默认加载:docker compose up -d
# 自动合并 docker-compose.yml + docker-compose.override.yml
# 2. 生产部署:docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
# 3. 指定环境:docker compose --env-file .env.prod up -d备份与恢复
#!/bin/bash
# backup.sh — 数据备份脚本
BACKUP_DIR="/data/backups/$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"
# 备份 PostgreSQL
docker compose exec -T postgres pg_dumpall -U appuser > "$BACKUP_DIR/postgres_backup.sql"
# 备份 Redis
docker compose exec -T redis redis-cli BGSAVE
sleep 5
docker cp redis:/data/dump.rdb "$BACKUP_DIR/redis_backup.rdb"
# 压缩备份
tar -czf "$BACKUP_DIR.tar.gz" "$BACKUP_DIR"
rm -rf "$BACKUP_DIR"
# 清理 7 天前的备份
find /data/backups -name "*.tar.gz" -mtime +7 -delete
echo "备份完成: $BACKUP_DIR.tar.gz"#!/bin/bash
# restore.sh — 数据恢复脚本
BACKUP_FILE=$1
if [ -z "$BACKUP_FILE" ]; then
echo "用法: ./restore.sh <backup_file.tar.gz>"
exit 1
fi
# 解压备份
tar -xzf "$BACKUP_FILE" -C /tmp
BACKUP_DIR=$(find /tmp -maxdepth 1 -name "*_*" -type d | head -1)
# 恢复 PostgreSQL
cat "$BACKUP_DIR/postgres_backup.sql" | docker compose exec -T postgres psql -U appuser -d appdb
# 恢复 Redis
docker cp "$BACKUP_DIR/redis_backup.rdb" redis:/data/dump.rdb
docker compose restart redis
echo "恢复完成"优点
缺点
总结
Docker Compose 在生产环境中的最佳实践涵盖了健康检查、资源限制、日志管理和更新策略等关键方面。通过合理的 healthcheck 配置确保服务可用性,通过 deploy.resources 限制防止单个容器占用过多资源,通过 json-file 日志驱动配合外部采集工具实现集中化日志管理。虽然 Docker Compose 在大规模分布式场景下无法替代 Kubernetes,但对于中小规模的应用部署,它以其简洁的配置和低运维成本仍然是一个非常实用的选择。
关键知识点
- DevOps 主题的核心是让交付更快、更稳、更可审计。
- 自动化不是把命令脚本化,而是把失败、回滚、权限和观测一起设计进去。
- 生产链路必须明确制品、环境、凭据、配置和责任边界。
- 部署主题通常要同时看镜像、容器、卷、网络和宿主机资源。
项目落地视角
- 把流水线拆成构建、测试、制品、部署、验证和回滚几个阶段。
- 为关键步骤补齐日志、指标、通知和人工兜底点。
- 定期演练扩容、回滚、故障注入和灾备切换。
- 固定镜像标签,记录端口、挂载目录、环境变量和自启动策略。
常见误区
- 只关注部署成功,不关注失败恢复和审计追踪。
- 把环境差异藏在临时脚本或人工操作里。
- 上线频率高了以后,没有标准化制品和配置管理。
- 使用 latest 导致结果不可复现。
进阶路线
- 继续补齐 GitOps、可观测性、平台工程和成本治理。
- 把主题和应用架构、安全、权限、备份恢复联动起来理解。
- 形成团队级平台能力,而不是每个项目重复造轮子。
- 继续补齐 Compose 编排、镜像瘦身、安全扫描和镜像仓库治理。
适用场景
- 当你准备把《Docker Compose 生产实践》真正落到项目里时,最适合先在一个独立模块或最小样例里验证关键路径。
- 适合构建自动化交付、基础设施治理、监控告警和生产发布体系。
- 当团队规模扩大、发布频率提升或环境变多时,这类主题会显著影响交付效率。
落地建议
- 所有自动化流程尽量做到幂等、可审计、可回滚。
- 把制品、变量、凭据和执行权限分层管理。
- 定期演练扩容、回滚、密钥轮换和灾备恢复。
排错清单
- 先定位失败发生在代码、构建、制品、环境还是权限层。
- 检查流水线变量、凭据、镜像标签和目标环境配置是否一致。
- 如果问题偶发,重点看并发发布、资源争抢和外部依赖抖动。
复盘问题
- 如果把《Docker Compose 生产实践》放进你的当前项目,最先要验证的输入、输出和失败路径分别是什么?
- 《Docker Compose 生产实践》最容易在什么规模、什么边界条件下暴露问题?你会用什么指标或日志去确认?
- 相比默认实现或替代方案,采用《Docker Compose 生产实践》最大的收益和代价分别是什么?
