2. Docker Compose 编排进阶:多服务编排、依赖管理、健康检查、环境变量与配置管理

在微服务架构中,单一容器的管理远不能满足生产级需求。Docker Compose 作为多容器编排的核心工具,其进阶能力决定了服务集群的稳定性与可维护性。本章将深入剖析多服务编排、依赖管理、健康检查以及环境变量与配置管理四大核心模块,帮助你在压测与契约测试场景中构建高可用的服务拓扑。

2.1 多服务编排:从单体到拓扑

多服务编排的核心在于将多个相互依赖的容器定义为单一应用栈。通过 docker-compose.yml 文件,你可以声明式地定义服务、网络、卷与端口映射,实现一键启动与销毁。

关键原则: 每个服务应遵循单一职责,避免在同一个容器中运行多个进程。编排文件应作为基础设施即代码(IaC)的入口,纳入版本控制。

以下是一个典型的多服务编排示例,包含 API 网关、用户服务、订单服务与数据库:

version: '3.8'

services:
  api-gateway:
    image: myapp/gateway:1.0
    ports:
      - "8080:8080"
    environment:
      - USER_SERVICE_URL=http://user-service:3001
      - ORDER_SERVICE_URL=http://order-service:3002
    networks:
      - frontend
      - backend

  user-service:
    image: myapp/user-service:1.0
    ports:
      - "3001:3001"
    environment:
      - DB_HOST=postgres-db
      - DB_PORT=5432
    depends_on:
      postgres-db:
        condition: service_healthy
    networks:
      - backend

  order-service:
    image: myapp/order-service:1.0
    ports:
      - "3002:3002"
    environment:
      - DB_HOST=postgres-db
      - DB_PORT=5432
    depends_on:
      postgres-db:
        condition: service_healthy
    networks:
      - backend

  postgres-db:
    image: postgres:15
    environment:
      POSTGRES_USER: app_user
      POSTGRES_PASSWORD: secure_pass
      POSTGRES_DB: microservices_db
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app_user -d microservices_db"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - backend

volumes:
  pgdata:

networks:
  frontend:
  backend:
网络隔离策略: 将 API 网关置于 frontend 与 backend 双网络中,而内部服务仅连接 backend 网络,可有效减少攻击面并提升安全性。

2.2 依赖管理:启动顺序与条件控制

微服务之间存在明确的启动依赖关系。Docker Compose 通过 depends_on 指令控制服务启动顺序,但默认仅等待容器启动,不保证服务就绪。进阶用法需结合健康检查实现条件依赖。

依赖模式 配置方式 行为说明 适用场景
简单依赖 depends_on: - db 仅等待 db 容器启动(不保证就绪) 快速开发环境
健康条件依赖 depends_on: db: condition: service_healthy 等待 db 容器通过健康检查后才启动 生产环境、压测场景
启动完成依赖 depends_on: db: condition: service_started 等待 db 容器启动完成(默认行为) 无健康检查的遗留服务
常见陷阱: 仅使用 depends_on 而不配置健康检查,可能导致上游服务在数据库尚未完成初始化时即开始连接,引发连接拒绝或数据不一致。在契约测试中,这种时序问题会直接导致测试失败。

2.3 健康检查:服务就绪的黄金标准

健康检查是确保服务真实可用的关键机制。Docker Compose 支持在服务级别定义 healthcheck 指令,通过周期性执行自定义命令判断服务状态。

健康检查的完整参数包括:

  • test:执行的检查命令,支持 CMD、CMD-SHELL 或 NONE(禁用)。
  • interval:检查间隔,默认 30s。
  • timeout:单次检查超时,默认 30s。
  • retries:连续失败次数后标记为 unhealthy,默认 3。
  • start_period:启动宽限期,在此期间失败不计入 retries。

以下为不同服务的健康检查配置示例:

# PostgreSQL 数据库
healthcheck:
  test: ["CMD-SHELL", "pg_isready -U app_user -d microservices_db"]
  interval: 10s
  timeout: 5s
  retries: 5
  start_period: 30s

# Redis 缓存
healthcheck:
  test: ["CMD", "redis-cli", "ping"]
  interval: 5s
  timeout: 3s
  retries: 3

# Spring Boot 应用(通过 Actuator)
healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
  interval: 15s
  timeout: 5s
  retries: 3
  start_period: 60s
压测场景建议: 在压测启动前,应通过 docker compose ps --services --filter "status=running" 结合健康状态检查,确保所有服务均为 healthy 状态,避免压测流量进入未就绪的服务。
健康检查与依赖管理流程 编排启动 解析 depends_on 依赖图 存在健康条件? 否 等待容器启动 是 等待健康检查通过 启动当前服务

2.4 环境变量与配置管理

环境变量是解耦配置与代码的核心手段。Docker Compose 提供多层级的变量注入方式,适用于不同环境(开发、测试、生产)。

2.4.1 变量注入方式对比

注入方式 配置位置 优先级 典型用途
内联 environment docker-compose.yml 高 少量固定配置
env_file 外部 .env 文件 中 环境差异化配置
shell 环境变量 宿主机 shell 低 CI/CD 动态注入
Docker 秘密 secrets 配置块 最高安全 密码、证书等敏感信息

2.4.2 环境文件最佳实践

推荐使用 .env 文件管理环境变量,并通过 env_file 指令引用。以下为典型的分环境配置结构:

# 项目目录结构
project/
├── docker-compose.yml
├── .env.dev          # 开发环境
├── .env.test         # 测试环境
├── .env.prod         # 生产环境
└── secrets/
    ├── db_password.txt
    └── api_key.txt

docker-compose.yml 中引用方式:

services:
  user-service:
    image: myapp/user-service:1.0
    env_file:
      - .env.dev
    environment:
      - SERVICE_NAME=user-service  # 覆盖 env_file 中的同名变量
    secrets:
      - db_password

secrets:
  db_password:
    file: ./secrets/db_password.txt
安全提醒: 切勿将 .env.prod 或 secrets/ 目录提交到版本控制。应在 .gitignore 中明确排除这些文件,并通过 CI/CD 的安全变量或密钥管理服务注入。

2.5 配置管理进阶:Configs 与 Secrets

对于非敏感配置文件(如 Nginx 配置、Logback 配置),Docker Compose 提供 configs 机制;对于敏感数据,使用 secrets 机制。两者均支持文件挂载与运行时注入。

Docker Compose 配置与秘密注入架构 外部配置文件 外部秘密文件 Compose 引擎 configs / secrets 解析与挂载 容器 A(只读配置) 容器 B(只读秘密) 容器 C(配置+秘密) 注入路径说明 1. configs:挂载到容器 /<config_name>,默认权限 0444,适用于 Nginx、Logback 等配置文件。 2. secrets:挂载到容器 /run/secrets/<secret_name>,仅存在于内存文件系统,不写入容器层。 3. 两者均支持 Swarm 模式下的加密传输,Compose 单机模式下为文件挂载。

2.6 压测场景下的编排最佳实践

在契约测试与压测场景中,Docker Compose 编排需要额外关注以下要点:

  • 资源限制:使用 deploy.resources.limits 为每个服务设置 CPU 和内存上限,避免压测时单服务耗尽宿主机资源。
  • 日志驱动:配置 logging 驱动为 json-file 并设置 max-size 和 max-file,防止压测产生海量日志撑爆磁盘。
  • 端口冲突规避:压测环境建议使用动态端口映射(ports: - "0:3001"),通过 docker compose port 获取实际端口。
  • 网络延迟模拟:结合 tc 命令或专用网络插件,在 Compose 网络中注入延迟与丢包,模拟真实生产网络条件。
压测编排检查清单:
  1. 所有依赖服务配置了 condition: service_healthy。
  2. 数据库等有状态服务配置了 start_period 避免启动阶段误判。
  3. 环境变量通过 .env.test 文件统一管理,不硬编码在 Compose 文件中。
  4. 敏感信息使用 secrets 机制,不通过环境变量传递。
  5. 资源限制已设置,防止压测流量导致 OOM。