Docker Compose 生产环境配置
本文介绍 Docker Compose 在生产环境中的最佳实践,包括 Compose 文件编写、网络配置、持久化存储以及安全设置。
概述
Docker Compose 是定义和运行多容器 Docker 应用的工具。本文将介绍如何在生产环境中正确配置 Docker Compose,确保应用的稳定性、安全性和可维护性。
Compose 文件结构
基础结构示例
version: '3.8'
services:
app:
image: myapp:latest
container_name: myapp
restart: unless-stopped
environment:
- NODE_ENV=production
- DB_HOST=db
ports:
- "8080:8080"
networks:
- backend
- frontend
depends_on:
- db
- cache
volumes:
- app-data:/app/data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
db:
image: postgres:15-alpine
container_name: myapp-db
restart: unless-stopped
environment:
POSTGRES_DB: myapp
POSTGRES_USER: dbuser
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
volumes:
- db-data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
networks:
- backend
secrets:
- db_password
cache:
image: redis:7-alpine
container_name: myapp-cache
restart: unless-stopped
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes:
- cache-data:/data
networks:
- backend
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # 禁止外部访问
volumes:
app-data:
driver: local
db-data:
driver: local
cache-data:
driver: local
secrets:
db_password:
file: ./secrets/db_password.txt
生产环境配置要点
1. 重启策略
services:
app:
restart: unless-stopped # 推荐生产环境使用
# 其他选项:
# restart: always # 总是重启(包括手动停止后)
# restart: on-failure # 仅在失败时重启
# restart: no # 不自动重启(开发环境)
2. 资源限制
services:
app:
deploy:
resources:
limits:
cpus: '2'
memory: 2G
reservations:
cpus: '1'
memory: 1G
3. 健康检查
services:
web:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
db:
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
网络配置
自定义网络
networks:
# 前端网络(可外部访问)
frontend:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/24
# 后端网络(仅内部通信)
backend:
driver: bridge
internal: true
ipam:
config:
- subnet: 172.20.1.0/24
# 使用现有网络
existing:
external: true
name: my-existing-network
服务网络配置
services:
proxy:
image: nginx:alpine
networks:
frontend:
ipv4_address: 172.20.0.10
backend:
aliases:
- gateway
app:
image: myapp:latest
networks:
- backend
expose:
- "8080" # 仅内部暴露,不映射到主机
持久化存储
命名卷
volumes:
postgres-data:
driver: local
driver_opts:
type: none
o: bind
device: /data/postgres
services:
db:
volumes:
- postgres-data:/var/lib/postgresql/data
绑定挂载
services:
app:
volumes:
# 配置目录(只读)
- ./config:/app/config:ro
# 数据目录
- /var/data/app:/app/data
# 日志目录
- /var/log/app:/app/logs
# 临时目录
- type: tmpfs
target: /tmp
tmpfs:
size: 100M
环境变量管理
使用 .env 文件
# .env 文件(不提交到版本控制)
NODE_ENV=production
DB_HOST=db
DB_PORT=5432
DB_NAME=myapp
DB_USER=appuser
DB_PASSWORD=secretpassword
REDIS_PASSWORD=redispass
APP_PORT=8080
# docker-compose.yml
services:
app:
image: myapp:latest
environment:
- NODE_ENV=${NODE_ENV}
- DB_HOST=${DB_HOST}
- DB_PORT=${DB_PORT}
ports:
- "${APP_PORT}:8080"
使用 Secrets
# docker-compose.yml
services:
db:
image: postgres:15-alpine
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
- db_root_password
secrets:
db_password:
file: ./secrets/db_password.txt
db_root_password:
file: ./secrets/db_root_password.txt
多环境配置
基础配置 + 环境覆盖
# docker-compose.yml(基础配置)
version: '3.8'
services:
app:
image: myapp:latest
ports:
- "8080:8080"
environment:
- LOG_LEVEL=info
# docker-compose.prod.yml(生产环境覆盖)
version: '3.8'
services:
app:
restart: unless-stopped
deploy:
resources:
limits:
cpus: '2'
memory: 2G
environment:
- NODE_ENV=production
- LOG_LEVEL=warn
# docker-compose.dev.yml(开发环境覆盖)
version: '3.8'
services:
app:
build: .
volumes:
- .:/app
- /app/node_modules
environment:
- NODE_ENV=development
- LOG_LEVEL=debug
启动命令
# 开发环境
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up
# 生产环境
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
# 或使用环境变量
COMPOSE_FILE=docker-compose.yml:docker-compose.prod.yml docker-compose up -d
日志管理
日志配置
services:
app:
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "10"
labels: "service_name,environment"
env: "OS_VERSION"
nginx:
logging:
driver: "syslog"
options:
syslog-address: "tcp://logs.example.com:514"
tag: "nginx-{{.Name}}"
集中式日志
services:
fluentd:
image: fluent/fluentd:v1.16
volumes:
- ./fluentd/conf:/fluentd/etc
ports:
- "24224:24224"
app:
image: myapp:latest
logging:
driver: fluentd
options:
fluentd-address: localhost:24224
tag: docker.myapp
安全加固
以非 root 用户运行
services:
app:
image: myapp:latest
user: "1000:1000"
read_only: true
tmpfs:
- /tmp
- /var/cache
安全选项
services:
app:
image: myapp:latest
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
sysctls:
- net.core.somaxconn=1024
只读根文件系统
services:
nginx:
image: nginx:alpine
read_only: true
tmpfs:
- /var/cache/nginx:noexec,nosuid,size=100m
- /var/run:noexec,nosuid,size=100m
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./html:/usr/share/nginx/html:ro
监控与告警
Prometheus 监控
services:
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus-data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
ports:
- "9090:9090"
grafana:
image: grafana/grafana:latest
volumes:
- grafana-data:/var/lib/grafana
- ./grafana/dashboards:/etc/grafana/provisioning/dashboards:ro
ports:
- "3000:3000"
depends_on:
- prometheus
备份策略
数据备份
services:
backup:
image: offen/docker-volume-backup:latest
environment:
BACKUP_CRON_EXPRESSION: "0 2 * * *"
BACKUP_RETENTION_DAYS: "30"
AWS_S3_BUCKET_NAME: my-backup-bucket
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY}
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_KEY}
volumes:
- db-data:/backup/db-data:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
常见问题处理
时区设置
services:
app:
image: myapp:latest
environment:
- TZ=Asia/Shanghai
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
DNS 配置
services:
app:
image: myapp:latest
dns:
- 8.8.8.8
- 8.8.4.4
dns_search:
- example.com
dns_options:
- ndots:1
部署命令
# 启动服务
docker-compose up -d
# 查看日志
docker-compose logs -f
# 查看特定服务日志
docker-compose logs -f app
# 重启服务
docker-compose restart app
# 更新服务
docker-compose pull
docker-compose up -d
# 停止并删除
docker-compose down
# 停止并删除卷(清理数据)
docker-compose down -v
# 扩展服务实例
docker-compose up -d --scale app=3
总结
本文介绍了 Docker Compose 在生产环境的配置方法:
- 基础配置:服务定义、重启策略、健康检查
- 网络配置:隔离前端和后端网络,提高安全性
- 持久化存储:命名卷和绑定挂载的合理使用
- 环境管理:.env 文件和 Secrets 的安全管理
- 多环境支持:基础配置 + 环境特定覆盖
- 安全加固:非 root 用户、只读文件系统、安全选项
- 运维管理:日志、监控、备份策略
通过遵循这些最佳实践,可以在生产环境中安全、稳定地运行 Docker Compose 应用。