4. Docker Compose 编排:服务定义、网络配置、依赖管理、环境变量

在微服务架构中,Docker Compose 是定义和运行多容器 Docker 应用的核心工具。本章聚焦于 Compose 文件的四大关键要素:服务定义、网络配置、依赖管理与环境变量。掌握这些要素,是构建可复现、可调试的微服务环境的基础。

4.1 服务定义:微服务的声明式描述

每个微服务在 docker-compose.yml 中对应一个 services 下的顶级键。服务定义的核心字段包括镜像来源、容器名称、端口映射、卷挂载以及重启策略。

字段 说明 常见值示例
image 指定使用的镜像,支持私有仓库地址 registry.example.com/user/api:v1.2
build 从 Dockerfile 构建镜像,可指定上下文路径 ./api
ports 宿主机端口与容器端口的映射关系 "8080:8080"
volumes 持久化数据或挂载配置文件 ./config:/app/config:ro
restart 容器退出后的重启策略 unless-stopped
故障排查要点: 服务定义中 container_name 若重复,Compose 会报错;ports 映射冲突(宿主机端口已被占用)是启动失败的常见原因,排查时优先检查端口占用情况。
version: "3.8"
services:
  user-service:
    image: myregistry/user-service:1.0.0
    container_name: user-svc
    ports:
      - "8081:8080"
    volumes:
      - ./logs/user:/var/log/app
    restart: unless-stopped

  order-service:
    build: ./order
    ports:
      - "8082:8080"
    restart: on-failure:3

4.2 网络配置:服务间通信的骨架

Docker Compose 默认创建一个名为 <项目名>_default 的桥接网络,所有服务自动加入该网络并通过服务名互相访问。但在微服务架构中,通常需要自定义网络来实现隔离、分层或跨主机通信。

最佳实践: 为前端网关、业务服务、数据层分别创建独立的网络,仅暴露必要的通信路径,减少攻击面。
networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
  database:
    driver: bridge

services:
  api-gateway:
    networks:
      - frontend
      - backend
  user-service:
    networks:
      - backend
      - database
  postgres:
    networks:
      - database
自定义网络隔离架构 frontend 网络 backend 网络 database 网络 API 网关 用户服务 订单服务 PostgreSQL 网关仅暴露 frontend 端口;业务服务跨 backend 通信;数据库仅对 backend 服务可见

4.3 依赖管理:控制启动顺序与健康检查

微服务之间存在启动顺序依赖,例如订单服务需要等待用户服务就绪。Compose 提供 depends_on 声明依赖关系,但该字段仅控制容器启动顺序,不保证服务内部进程已就绪。生产环境应配合 healthcheck 实现真正的依赖等待。

机制 作用 局限性
depends_on 控制容器创建与启动顺序 不等待服务内部就绪,仅保证容器已启动
healthcheck 定期检查容器内进程是否健康 需要服务暴露健康端点或支持命令检测
condition: service_healthy 在 depends_on 中等待健康状态 Compose v3.8+ 支持,需配合 healthcheck 使用
常见故障: 仅使用 depends_on 而未配置健康检查,导致依赖服务尚未完成数据库迁移或缓存预热,上游服务连接失败。排查时观察容器日志中的连接重试与超时信息。
services:
  postgres:
    image: postgres:15
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app"]
      interval: 5s
      timeout: 3s
      retries: 5

  user-service:
    image: user-service:1.0
    depends_on:
      postgres:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
      interval: 10s
      timeout: 5s
      retries: 3

  order-service:
    image: order-service:1.0
    depends_on:
      user-service:
        condition: service_healthy
      postgres:
        condition: service_healthy

4.4 环境变量:配置注入与多环境管理

环境变量是微服务配置注入的标准方式,Compose 支持多种注入途径:直接在 environment 字段定义、引用宿主机变量、使用 .env 文件批量加载。

  • 直接定义: 适用于少量固定值,如 SPRING_PROFILES_ACTIVE=prod。
  • 宿主机变量引用: 使用 ${HOST_VAR} 语法,敏感信息可通过宿主机环境传入。
  • .env 文件: 项目根目录下的 .env 文件自动加载,适合管理多环境差异。
故障排查技巧: 使用 docker compose config 命令查看 Compose 文件解析后的最终配置,确认环境变量是否被正确替换。若变量未定义,Compose 会保留 ${VAR} 字面量,导致服务启动异常。
# .env 文件
DB_HOST=postgres
DB_PORT=5432
DB_USER=app_user
DB_PASSWORD=${DB_PASSWORD}   # 从宿主机环境读取,不写入文件

# docker-compose.yml
services:
  user-service:
    image: user-service:1.0
    environment:
      - SPRING_PROFILES_ACTIVE=prod
      - DB_HOST=${DB_HOST}
      - DB_PORT=${DB_PORT}
      - DB_USER=${DB_USER}
      - DB_PASSWORD=${DB_PASSWORD}
    env_file:
      - ./config/common.env
环境变量注入流程 宿主机环境变量 export DB_PASSWORD=xxx .env 文件 DB_HOST=postgres environment 字段 SPRING_PROFILES_ACTIVE Compose 解析合并 容器内环境变量 优先级:environment > .env > 宿主机默认值 同名变量以高优先级为准

4.5 综合编排示例:三服务微服务栈

以下是一个包含 API 网关、用户服务、PostgreSQL 的完整编排示例,整合了服务定义、网络隔离、健康检查依赖与环境变量管理。

version: "3.8"

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge

services:
  api-gateway:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    networks:
      - frontend
      - backend
    depends_on:
      user-service:
        condition: service_healthy
    restart: unless-stopped

  user-service:
    image: user-service:1.0.0
    environment:
      - SPRING_PROFILES_ACTIVE=prod
      - DB_HOST=postgres
      - DB_PORT=5432
      - DB_USER=${DB_USER}
      - DB_PASSWORD=${DB_PASSWORD}
    networks:
      - backend
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
      interval: 10s
      timeout: 5s
      retries: 3
    depends_on:
      postgres:
        condition: service_healthy
    restart: unless-stopped

  postgres:
    image: postgres:15
    environment:
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASSWORD}
      - POSTGRES_DB=userdb
    volumes:
      - pgdata:/var/lib/postgresql/data
    networks:
      - backend
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"]
      interval: 5s
      timeout: 3s
      retries: 5
    restart: unless-stopped

volumes:
  pgdata:
调试命令速查:
docker compose config — 验证 Compose 文件语法与变量替换
docker compose ps — 查看服务运行状态与端口映射
docker compose logs -f <service> — 跟踪特定服务的实时日志
docker compose exec <service> sh — 进入容器内部排查网络连通性