后端工程Technical Deep Dive

Docker Compose 多容器编排实战

发布时间2026/03/29
分类后端工程
预计阅读8 分钟
作者吴长龙
*

Docker Compose 多容器编排实战

01.内容

# Docker Compose 多容器编排实战

单个容器很简单,但真实应用通常由多个服务组成。Docker Compose 让你用 YAML 文件定义和管理多容器应用,是本地开发和小型部署的首选。

02.一、快速开始

1.1 docker-compose.yml 结构

yaml snippetyaml
version: '3.8'

services:
  # 应用服务
  api:
    build: ./api
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DB_HOST=db
    depends_on:
      - db
      - redis
    restart: unless-stopped

  # 数据库
  db:
    image: postgres:15-alpine
    volumes:
      - postgres-data:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
    restart: unless-stopped

  # 缓存
  redis:
    image: redis:7-alpine
    volumes:
      - redis-data:/data
    restart: unless-stopped

  # 反向代理
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - api
    restart: unless-stopped

volumes:
  postgres-data:
  redis-data:

1.2 常用命令

bash snippetbash
# 启动所有服务
docker-compose up -d

# 查看日志
docker-compose logs -f api
docker-compose logs -f  # 所有服务

# 查看状态
docker-compose ps

# 停止服务
docker-compose down

# 重新构建
docker-compose up -d --build

# 扩展服务(需要 docker-compose v2+)
docker-compose up -d --scale api=3

# 执行命令
docker-compose exec api sh
docker-compose exec db psql -U user -d myapp

03.二、开发环境配置

2.1 本地开发

yaml snippetyaml
# docker-compose.dev.yml
version: '3.8'

services:
  api:
    build:
      context: .
      target: development
    volumes:
      - .:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development
      - WATCH=true
    command: npm run dev
    ports:
      - "3000:3000"
      - "9229:9229"  # Debug 端口

  db:
    image: postgres:15
    ports:
      - "5432:5432"
    environment:
      POSTGRES_DB: myapp_dev
      POSTGRES_USER: dev
      POSTGRES_PASSWORD: dev

  redis:
    image: redis:7
    ports:
      - "6379:6379"
bash snippetbash
# 开发启动
docker-compose -f docker-compose.dev.yml up

2.2 环境变量文件

bash snippetbash
# .env 文件
POSTGRES_DB=myapp
POSTGRES_USER=user
POSTGRES_PASSWORD=secret_password
REDIS_PASSWORD=redis_secret
JWT_SECRET=your-jwt-secret

# docker-compose.yml 引用
services:
  db:
    image: postgres:15
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}

04.三、进阶配置

3.1 健康检查

yaml snippetyaml
services:
  api:
    build: .
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

  db:
    image: postgres:15
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user -d myapp"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 3s
      retries: 3

3.2 依赖等待

yaml snippetyaml
services:
  api:
    build: .
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    # 使用 wait-for-it 或 dockerize 等待
    entrypoint: ["./wait-for-it.sh", "db:5432", "--", "npm", "start"]

3.3 网络配置

yaml snippetyaml
services:
  api:
    networks:
      - backend
      - frontend

  web:
    networks:
      - frontend

  nginx:
    networks:
      - frontend

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true  # 禁止外部访问

05.四、生产环境建议

yaml snippetyaml
# docker-compose.prod.yml
version: '3.8'

services:
  api:
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s

  nginx:
    volumes:
      - ./ssl:/etc/nginx/ssl:ro
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

06.五、最佳实践

  • [ ] 开发/生产环境分离配置
  • [ ] 使用 .dockerignore 减少构建上下文
  • [ ] 敏感信息使用 .env 文件(不提交)
  • [ ] 添加健康检查
  • [ ] 合理设置资源限制
  • [ ] 使用命名卷持久化数据

---

*对于更复杂的生产环境,需要使用 Kubernetes 进行容器编排。*