結論先講
Docker Compose 上生產不是「湊合用」,是正確的選擇——前提是你配對了。 health check、restart policy、resource limits、log rotation、備份——這五件事做好,Docker Compose 在 1000 人以內比 K8s 更穩定、更便宜、更好 debug。
生產等級的 docker-compose.yml
version: '3.8'
services:
app:
image: your-app:${VERSION:-latest}
restart: unless-stopped # 掛了自動重啟
deploy:
resources:
limits:
cpus: '2.0'
memory: 2G
reservations:
cpus: '1.0'
memory: 1G
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "5" # 最多 5 個 50MB = 250MB
environment:
- NODE_ENV=production
- DB_HOST=postgres
- REDIS_HOST=redis
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
nginx:
image: nginx:alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./certs:/etc/nginx/certs:ro
depends_on:
app:
condition: service_healthy
postgres:
image: postgres:16-alpine
restart: unless-stopped
deploy:
resources:
limits:
cpus: '2.0'
memory: 4G
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
volumes:
- pg_data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
redis:
image: redis:7-alpine
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 3
volumes:
- redis_data:/data
volumes:
pg_data:
redis_data:五個關鍵配置
| 配置 | 為什麼 |
|---|---|
restart: unless-stopped | 服務掛了自動重啟,除非你手動 stop |
healthcheck | Docker 定期檢查服務是否健康,不健康就重啟 |
deploy.resources.limits | 防止一個 container 吃掉所有資源 |
logging.max-size + max-file | 防止 log 吃爆磁碟 |
depends_on: condition: service_healthy | 確保依賴的服務(DB、Redis)啟動完成後才啟動 app |
部署流程
Zero Downtime 部署(簡易版)
#!/bin/bash
# deploy.sh
# 1. Pull 新 image
docker compose pull app
# 2. 滾動更新(先啟動新的,再停舊的)
docker compose up -d --no-deps --scale app=2 app
sleep 10 # 等新 container 健康
# 3. 停掉舊的
docker compose up -d --no-deps --scale app=1 app不如 K8s 的 rolling update 優雅,但對 1000 人以內的系統夠用。
更安全的做法:Blue-Green
# 跑兩套 app(blue + green),nginx 切換
docker compose -f docker-compose.blue.yml up -d
# 測試 blue 正常
# 修改 nginx upstream 指向 blue
docker compose -f docker-compose.green.yml down監控
沒有 K8s 的 Prometheus operator,但你可以用:
| 工具 | 用途 | Docker Compose 友好度 |
|---|---|---|
| Portainer | Container 管理 UI | 最佳(專為 Docker 設計) |
| Grafana + Prometheus | 指標監控 | 好(compose 加兩個 service) |
| Loki | Log 收集 | 好(取代 ELK,更輕量) |
| Uptime Kuma | Health check 監控 | 好(一個 container) |
備份策略
K8s 有 Velero 做叢集備份。Docker Compose 用 cron + 腳本:
# backup.sh — 每天凌晨 3 點跑
#!/bin/bash
# DB 備份
docker compose exec -T postgres pg_dump -U postgres mydb > /backup/db_$(date +%Y%m%d).sql
# Redis 備份(RDB snapshot)
docker compose exec -T redis redis-cli BGSAVE
cp /var/lib/docker/volumes/redis_data/_data/dump.rdb /backup/redis_$(date +%Y%m%d).rdb
# 保留最近 30 天
find /backup -mtime +30 -delete簡單但有效。
Docker Compose 的真實限制
| 限制 | 影響 | 解法 |
|---|---|---|
| 單機天花板 | 1 台機器的 CPU/RAM 是上限 | nginx LB 多台 |
| 沒有自動擴縮 | 流量暴增時不會自動加 container | 手動 scale 或上 K8s |
| 跨機器困難 | Docker Compose 設計給單機 | Docker Swarm 或 K8s |
| 秘密管理粗糙 | .env 檔明文存密碼 | Docker Secrets 或 Vault |
當你碰到這些限制中的任何一個,就是考慮上 K8s 的時候。 但在那之前,Docker Compose 是更好的選擇。
下一篇
可觀測性(一):分散式 Tracing — 一個請求跨三個服務,出問題了怎麼追?OpenTelemetry + Jaeger 讓你看到完整的請求鏈路——哪個服務花了多少時間、在哪裡卡住。
本系列文章
完整 68 篇目錄見 系列首頁
← 上一篇:Docker Compose vs K8s:1000 人是分水嶺 → 下一篇:可觀測性(一):分散式 Tracing 怎麼追一個請求