Docker Compose 多容器编排实战:从开发到生产的完整指南

在现代微服务架构中,一个应用往往由多个服务组成:Web 应用、数据库、缓存、消息队列等。Docker Compose 提供了一种声明式的方式来定义和管理多容器应用,让开发者能够用一条命令启动整个应用栈。本文将从开发环境搭建到生产部署,系统讲解 Docker Compose 的实战技巧。

一、Compose 文件结构详解

docker-compose.yml 是 Docker Compose 的核心配置文件,使用 YAML 格式描述多容器应用。以下是一个典型的 Web 应用栈配置:

version: '3.8'

services:
  webapp:
    build:
      context: ./webapp
      dockerfile: Dockerfile.prod
    ports:
      - "8080:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=prod
      - DB_HOST=postgres
      - REDIS_HOST=redis
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_started
    restart: unless-stopped
    networks:
      - app-network

  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: appuser
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    volumes:
      - postgres-data:/var/lib/postgresql/data
      - ./init-scripts:/docker-entrypoint-initdb.d
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U appuser -d myapp"]
      interval: 10s
      timeout: 5s
      retries: 5
    secrets:
      - db_password
    networks:
      - app-network

  redis:
    image: redis:7-alpine
    command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
    volumes:
      - redis-data:/data
    networks:
      - app-network

volumes:
  postgres-data:
  redis-data:

networks:
  app-network:
    driver: bridge

secrets:
  db_password:
    file: ./secrets/db_password.txt

二、多环境配置管理

实际项目中通常需要区分开发、测试和生产环境。Docker Compose 支持通过多个配置文件叠加来实现环境隔离。

基础配置文件 docker-compose.yml 定义公共部分,环境特定配置通过 -f 参数叠加:

# docker-compose.dev.yml(开发环境覆盖配置)
services:
  webapp:
    build:
      dockerfile: Dockerfile.dev
    volumes:
      - ./webapp/src:/app/src
      - ./webapp/config:/app/config
    environment:
      - SPRING_PROFILES_ACTIVE=dev
      - DEBUG=true
    ports:
      - "8080:8080"
      - "5005:5005"

  postgres:
    ports:
      - "5432:5432"
# docker-compose.prod.yml(生产环境覆盖配置)
services:
  webapp:
    build:
      dockerfile: Dockerfile.prod
    environment:
      - SPRING_PROFILES_ACTIVE=prod
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: '2'
          memory: 1G
        reservations:
          cpus: '0.5'
          memory: 256M
      restart_policy:
        condition: any
        delay: 5s
        max_attempts: 3
    ports:
      - "80:8080"

启动时通过 -f 参数叠加配置文件:

# 开发环境
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d

# 生产环境
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

三、健康检查与启动顺序控制

多容器应用中最常见的问题是服务间的启动顺序依赖。depends_on 的 condition 属性提供了精细的控制能力:

services:
  webapp:
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_started
      migration:
        condition: service_completed_successfully

  migration:
    build: ./migration
    depends_on:
      postgres:
        condition: service_healthy
    command: ["flyway", "migrate"]

service_completed_successfully 是一个非常有用的条件,适用于需要在主应用启动前执行数据库迁移、数据初始化等一次性任务的场景。

四、日志管理策略

容器日志如果不加以管理,很容易撑满磁盘。推荐使用 JSON 文件日志驱动配合日志轮转:

services:
  webapp:
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"
        labels: "service,env"

  postgres:
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "5"

对于生产环境,建议将日志统一收集到 ELK 或 Loki 等日志中心:

services:
  webapp:
    logging:
      driver: fluentd
      options:
        fluentd-address: localhost:24224
        tag: webapp.log

五、资源限制与性能优化

在共享主机上运行多个容器时,资源限制是防止某个容器耗尽系统资源的关键手段:

services:
  webapp:
    deploy:
      resources:
        limits:
          cpus: '2.0'
          memory: 2G
        reservations:
          cpus: '0.5'
          memory: 512M

  postgres:
    deploy:
      resources:
        limits:
          cpus: '4.0'
          memory: 4G
        reservations:
          cpus: '1.0'
          memory: 1G

同时建议为数据库容器配置共享内存,以提升查询性能:

postgres:
  image: postgres:16-alpine
  shm_size: 256mb
  sysctls:
    - net.core.somaxconn=1024
  ulimits:
    nofile:
      soft: 65536
      hard: 65536

六、CI/CD 集成

Docker Compose 可以很好地融入 CI/CD 流水线。以下是一个 GitLab CI 配置示例:

stages:
  - test
  - build
  - deploy

test:
  stage: test
  script:
    - docker compose -f docker-compose.test.yml up --abort-on-container-exit --exit-code webapp
  after_script:
    - docker compose down -v

build:
  stage: build
  script:
    - docker compose build webapp
    - docker tag myapp-webapp:latest registry.example.com/webapp:$CI_COMMIT_SHA
    - docker push registry.example.com/webapp:$CI_COMMIT_SHA
  only:
    - main

deploy:
  stage: deploy
  script:
    - ssh prod-server "cd /app && docker compose pull && docker compose up -d --remove-orphans"
  only:
    - main
  when: manual

七、常用运维命令速查

# 启动所有服务(后台运行)
docker compose up -d

# 查看服务状态
docker compose ps

# 查看实时日志
docker compose logs -f webapp

# 重新构建并启动
docker compose up -d --build webapp

# 扩展服务实例数
docker compose up -d --scale worker=3

# 进入容器执行命令
docker compose exec webapp sh

# 停止并删除容器、网络(保留数据卷)
docker compose down

# 停止并删除所有(包括数据卷)
docker compose down -v

# 查看资源使用情况
docker compose stats

总结

Docker Compose 是管理多容器应用的利器,从开发到生产都有广泛的应用场景。关键实践包括:使用多文件覆盖实现环境隔离、通过健康检查和启动条件控制服务依赖、配置日志轮转防止磁盘溢出、设置资源限制保障系统稳定,以及集成 CI/CD 实现自动化部署。对于更复杂的集群编排需求,可以平滑迁移到 Kubernetes,但中小规模应用场景下 Docker Compose 依然是最轻量高效的选择。