进阶2-3 小时·容器化部署

Docker Compose 多服务编排

使用 Docker Compose 编排一个包含 Web 应用、数据库、Redis、Nginx 的完整服务栈

Dockercomposenginxredispostgresql

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  # 服务编排定义

最佳实践

  1. 使用 depends_on:确保服务启动顺序
  2. 数据持久化:使用 volumes 保存数据库数据
  3. 网络隔离:使用自定义网络隔离服务
  4. 环境变量:使用环境变量管理配置
  5. 健康检查:添加 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

扩展挑战

  1. 添加健康检查
  2. 实现服务自动重启
  3. 添加日志收集

相关课程

课程相关章节
DockerDocker Compose 基础
DockerCompose YAML 语法
DockerBridge 网络
Docker命名卷