Docker Compose 单机管理
当你有 Web、数据库、缓存等多个服务时,Compose 是单机运维的高性价比方案。
Compose 服务编排结构
graph LR
A[docker-compose.yml] --> B[web :3000]
A --> C[db postgres :5432]
A --> D[redis :6379]
B -->|depends_on| C
B -->|depends_on| D
C --> E[Named Volume: db_data]
B --> F[Named Volume: uploads]
生产级 docker-compose.yml
# docker-compose.yml
services:
web:
image: myapp:latest
restart: unless-stopped # 除非手动停止,否则自动重启
ports:
- "127.0.0.1:3000:3000" # 只绑定 localhost,通过 Nginx 对外暴露
env_file:
- /etc/myapp/myapp.env # 生产 Secrets 从外部注入
volumes:
- uploads:/app/uploads # 用户上传文件持久化
depends_on:
db:
condition: service_healthy # 等待 DB 健康检查通过再启动
redis:
condition: service_started
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s # 启动后等待 10s 再开始检查
deploy:
resources:
limits:
memory: 512M # 防止内存泄漏撑满服务器
cpus: "0.5"
logging:
driver: "json-file"
options:
max-size: "50m" # 单个日志文件最大 50MB
max-file: "5" # 最多保留 5 个文件
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: myapp
POSTGRES_USER: app
POSTGRES_PASSWORD_FILE: /run/secrets/db_password # 更安全的方式
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d myapp"]
interval: 10s
timeout: 5s
retries: 5
deploy:
resources:
limits:
memory: 256M
redis:
image: redis:7-alpine
restart: unless-stopped
command: redis-server --maxmemory 128mb --maxmemory-policy allkeys-lru
volumes:
- redis_data:/data
volumes:
db_data: # 数据库数据(宿主机 /var/lib/docker/volumes/...)
redis_data:
uploads:
常用 Compose 操作命令
# 启动所有服务(后台运行)
docker compose up -d
# 查看状态和健康检查结果
docker compose ps
# 查看实时日志
docker compose logs -f
docker compose logs -f web # 只看 web 服务
# 重启单个服务(不影响其他)
docker compose restart web
# 拉取新镜像并重建服务(零停机策略)
docker compose pull web
docker compose up -d --no-deps web # 只重建 web,不重建 db/redis
# 停止并删除所有容器(数据卷保留)
docker compose down
# 完全清除(含数据卷)— 危险!
docker compose down -v
健康检查状态查看
# 查看健康检查状态
docker compose ps
# NAME IMAGE STATUS
# web myapp:latest Up 2 hours (healthy)
# db postgres:16 Up 2 hours (healthy)
# 查看健康检查历史(最后 5 次)
docker inspect myapp_web_1 | jq '.[0].State.Health.Log[-5:]'
Compose 适用场景对比
| 场景 | 是否合适 | 说明 |
|---|---|---|
| 单机小系统(< 10 服务) | ✅ 非常合适 | 成本低,运维简单 |
| 开发/测试环境 | ✅ 非常合适 | 一键启动完整依赖 |
| 简单生产环境(1 台服务器) | ✅ 可以 | 配合 Nginx 反向代理 |
| 需要跨机器扩容 | ❌ 不够 | 考虑 Docker Swarm 或 Kubernetes |
| 服务数量 > 20 | ⚠️ 管理复杂 | 考虑更完整的编排方案 |
常见误区
| 误区 | 正确做法 |
|---|---|
ports: "3000:3000" 直接绑定所有网卡 | 用 "127.0.0.1:3000:3000" 只绑定 localhost,通过 Nginx 对外 |
不设置 healthcheck,直接 depends_on: db | depends_on 只等容器启动,不等服务就绪;必须加 condition: service_healthy |
不设置 memory 限制 | 无限制的容器会在内存泄漏时把整台服务器打崩 |
更新镜像时 docker compose down && up | 用 docker compose up -d --no-deps web 只更新特定服务,数据库不受影响 |
| 日志不设上限 | 不加 logging 配置,容器日志可能填满磁盘 |
本节执行清单
- [ ] 用 Compose 启动 web + db 至少两个服务
- [ ] 为 db 配置 healthcheck,web 使用
condition: service_healthy - [ ] 设置 memory 资源限制(防止单容器占满内存)
- [ ] 配置 logging 上限(
max-size: 50m, max-file: 5) - [ ] 记录容器重建时哪些数据会丢(确认数据卷已配置)
下一节:什么时候用 Docker,什么时候不用 Kubernetes——先建立清晰边界,避免过度设计。