Docker Compose 不只是开发工具。在中小规模生产环境中,它同样能胜任。本文分享如何用 Compose 编排一个包含 6 个服务的完整应用栈,以及踩过的坑。
caddy
:80 :443
~45MB
app-api
:3000
~280MB
app-worker
—
~190MB
postgres
:5432
~512MB
redis
:6379
~128MB
minio
:9000
~340MB
一、compose.yaml 编排
# compose.yaml — 生产环境
services:
caddy:
image: caddy:2-alpine
ports: ["80:80", "443:443"]
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
restart: unless-stopped
networks: [frontend]
app-api:
build: { context: ., dockerfile: Dockerfile }
command: node dist/server.js
env_file: .env
deploy:
resources:
limits: { memory: 512M, cpus: '1.0' }
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 5s
retries: 3
depends_on:
postgres: { condition: service_healthy }
redis: { condition: service_healthy }
networks: [frontend, backend]
restart: unless-stopped
postgres:
image: postgres:16-alpine
volumes: [pgdata:/var/lib/postgresql/data]
environment:
POSTGRES_DB: ${DB_NAME}
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASS}
healthcheck:
test: ["CMD", "pg_isready"]
networks: [backend]
restart: unless-stopped
redis:
image: redis:7-alpine
command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
volumes: [redis_data:/data]
healthcheck:
test: ["CMD", "redis-cli", "ping"]
networks: [backend]
restart: unless-stopped
volumes:
caddy_data: { driver: local, driver_opts: { type: none, o: bind, device: /data/volumes/caddy_data } }
pgdata: { driver: local, driver_opts: { type: none, o: bind, device: /data/volumes/pgdata } }
redis_data: { driver: local, driver_opts: { type: none, o: bind, device: /data/volumes/redis_data } }
networks:
frontend: { driver: bridge }
backend: { driver: bridge }
二、关键实践
2.1 健康检查与启动顺序
Compose 的 depends_on 配合 condition: service_healthy,确保数据库完全就绪后才启动应用。这比 sleep 等待可靠得多。
2.2 资源限制
生产环境必须设置 deploy.resources.limits,防止一个容器 OOM 拖垮整个主机。
2.3 数据持久化
⚠️ 数据安全:永远使用 bind mount 而非 Docker volume 来存储数据库数据。这样即使
docker compose down 误操作,数据也不会丢失。同时记得定期备份。
三、日志管理
# docker-compose 日志配置
services:
app-api:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
tag: "{{.Name}}"
配合 docker compose logs -f --tail=100 查看实时日志,生产环境用 Loki + Promtail 收集更佳。
四、备份脚本
#!/bin/bash
# backup.sh — 每日备份
BACKUP_DIR="/data/backups/$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR
# PostgreSQL 备份
docker compose exec -T postgres pg_dump -U app myapp | gzip > $BACKUP_DIR/db.sql.gz
# Redis 备份
docker compose exec -T redis redis-cli BGSAVE
cp /data/volumes/redis_data/dump.rdb $BACKUP_DIR/
# 保留最近 7 天
find /data/backups -mtime +7 -exec rm -rf {} +
echo "Backup done: $BACKUP_DIR"
五、总结
- Compose 适合 单机多服务 场景,不需要 K8s 的复杂度
- 健康检查 + depends_on 是正确启动顺序的关键
- bind mount + 定期备份 是数据安全的基本功
- 资源限制 必须配,否则一个容器就能打垮整台机器