Docker Compose 多服务编排
使用 Docker Compose 编排一个包含 Web 应用、数据库、Redis、Nginx 的完整服务栈
你将学到
- 使用 Docker Compose 定义多容器应用
- 配置服务间的网络通信
- 管理数据持久化
- 使用 Nginx 作为反向代理
前置知识
架构设计
┌─────────────────────────────────────────┐
│ Nginx │
│ (反向代理) │
└───────────────┬─────────────────────────┘
│
┌───────────┴───────────┐
│ │
▼ ▼
┌─────────┐ ┌─────────┐
│ Web 1 │ │ Web 2 │
│ (Flask) │ │ (Flask) │
└────┬────┘ └────┬────┘
│ │
└─────────┬───────────┘
│
┌──────────┴──────────┐
│ │
▼ ▼
┌─────────┐ ┌─────────┐
│ DB │ │ Redis │
│ (PG) │ │ (缓存) │
└─────────┘ └─────────┘
实现步骤
第一步:项目结构
multi-service/
├── app/
│ ├── Dockerfile
│ ├── requirements.txt
│ └── app.py
├── nginx/
│ └── nginx.conf
└── docker-compose.yml
第二步:Web 应用
# app/app.py
from flask import Flask, jsonify
import redis
import psycopg2
import os
app = Flask(__name__)
def get_redis():
return redis.Redis(host="redis", port=6379, decode_responses=True)
def get_db():
return psycopg2.connect(
host="db",
database=os.getenv("POSTGRES_DB", "mydb"),
user=os.getenv("POSTGRES_USER", "user"),
password=os.getenv("POSTGRES_PASSWORD", "password")
)
@app.route("/")
def index():
r = get_redis()
visits = r.incr("visits")
return jsonify({"message": "Hello!", "visits": visits})
@app.route("/users")
def users():
conn = get_db()
cur = conn.cursor()
cur.execute("SELECT id, name FROM users")
users = [{"id": row[0], "name": row[1]} for row in cur.fetchall()]
cur.close()
conn.close()
return jsonify({"users": users})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
# app/requirements.txt
flask==3.0.0
redis==5.0.0
psycopg2-binary==2.9.9
# app/Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]
第三步:Nginx 配置
# nginx/nginx.conf
upstream web {
server web1:5000;
server web2:5000;
}
server {
listen 80;
location / {
proxy_pass http://web;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
第四步:Docker Compose
# docker-compose.yml
version: "3.8"
services:
web1:
build: ./app
environment:
- POSTGRES_DB=mydb
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
depends_on:
- db
- redis
networks:
- app-network
web2:
build: ./app
environment:
- POSTGRES_DB=mydb
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
depends_on:
- db
- redis
networks:
- app-network
db:
image: postgres:15-alpine
environment:
- POSTGRES_DB=mydb
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- app-network
redis:
image: redis:7-alpine
volumes:
- redis-data:/data
networks:
- app-network
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- web1
- web2
networks:
- app-network
volumes:
postgres-data:
redis-data:
networks:
app-network:
driver: bridge
第五步:启动服务
# 构建并启动所有服务
docker-compose up -d
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs -f web1
# 停止服务
docker-compose down
# 停止并删除数据卷
docker-compose down -v
完整项目结构
multi-service/
├── app/
│ ├── Dockerfile # Web 应用镜像
│ ├── requirements.txt
│ └── app.py # Flask 应用
├── nginx/
│ └── nginx.conf # Nginx 反向代理配置
└── docker-compose.yml # 服务编排定义
最佳实践
- 使用 depends_on:确保服务启动顺序
- 数据持久化:使用 volumes 保存数据库数据
- 网络隔离:使用自定义网络隔离服务
- 环境变量:使用环境变量管理配置
- 健康检查:添加 healthcheck 确保服务可用
常见问题
Q: 如何查看服务日志?
A: docker-compose logs -f [service_name]
Q: 如何扩展 Web 服务?
A: docker-compose up -d --scale web1=3
Q: 如何更新单个服务?
A: docker-compose up -d --build web1
扩展挑战
- 添加健康检查
- 实现服务自动重启
- 添加日志收集
相关课程
| 课程 | 相关章节 |
|---|---|
| Docker | Docker Compose 基础 |
| Docker | Compose YAML 语法 |
| Docker | Bridge 网络 |
| Docker | 命名卷 |