实际项目中,一个应用往往需要多个服务配合运行。Docker Compose 是管理多容器应用的标准工具,一个 YAML 文件定义所有服务。
docker-compose.yml 基本结构
version: "3.8"
services:
web:
image: nginx:alpine
ports:
- "80:80"
app:
build: ./app
environment:
- REDIS_HOST=redis
redis:
image: redis:6-alpine
networks:
default:
driver: bridge
volumes:
data:
三个核心部分:services 定义容器、networks 定义网络、volumes 定义持久化存储。
实战:nginx + Flask + Redis
项目结构:
project/
├── docker-compose.yml
├── nginx/
│ └── nginx.conf
├── app/
│ ├── Dockerfile
│ ├── app.py
│ └── requirements.txt
app/app.py:
from flask import Flask, jsonify
import redis
app = Flask(__name__)
r = redis.Redis(host='redis', port=6379, decode_responses=True)
@app.route('/')
def index():
count = r.incr('hits')
return jsonify({"message": "Hello", "visits": count})
@app.route('/health')
def health():
return jsonify({"status": "ok"})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
app/Dockerfile:
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]
app/nequirements.txt:
flask==2.0.1
redis==3.5.3
nginx/nginx.conf:
upstream flask_app {
server app:5000;
}
server {
listen 80;
location / {
proxy_pass http://flask_app;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
docker-compose.yml:
version: "3.8"
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- app
restart: unless-stopped
app:
build: ./app
expose:
- "5000"
environment:
- FLASK_ENV=production
depends_on:
- redis
restart: unless-stopped
deploy:
replicas: 2
redis:
image: redis:6-alpine
volumes:
- redis_data:/data
command: redis-server --appendonly yes
restart: unless-stopped
volumes:
redis_data:
常用命令
# 启动所有服务(后台运行)
docker-compose up -d
# 查看运行状态
docker-compose ps
# 查看日志
docker-compose logs -f app
# 只重建某个服务
docker-compose up -d --build app
# 停止并删除所有容器
docker-compose down
# 停止并删除容器+数据卷(慎用)
docker-compose down -v
# 进入某个容器
docker-compose exec app sh
# 扩缩容
docker-compose up -d --scale app=3
环境变量管理
用 .env 文件管理环境变量:
# .env
REDIS_VERSION=6-alpine
FLASK_PORT=5000
在 docker-compose.yml 中引用:
services:
redis:
image: redis:${REDIS_VERSION}
app:
environment:
- PORT=${FLASK_PORT}
depends_on 的局限
depends_on 只保证启动顺序,不保证服务就绪。Redis 启动后到可接受连接有一小段时间,app 可能连接失败。解决方案:
- 应用代码里做重试逻辑
- 使用 healthcheck + condition:
services:
redis:
image: redis:6-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
retries: 3
app:
depends_on:
redis:
condition: service_healthy
小结
Docker Compose 适合开发和测试环境的多容器编排。生产环境如果需要跨主机部署、自动伸缩,应该考虑 Kubernetes。但对于中小项目,Compose 配合一台服务器完全够用。