第4章 网络配置与依赖管理:自定义网络、依赖启动顺序(depends_on)、健康检查(healthcheck)

4.1 原理概述

在 Compose 编排中,服务之间的网络连通性、启动顺序以及运行状态监测是决定测试环境稳定性的关键因素。自定义网络(Custom Network)让同组服务在隔离的虚拟子网中通信;depends_on 控制服务间的启动先后;健康检查(healthcheck)则确保上游服务在实际就绪后才被下游依赖。

  • 自定义网络:Docker 创建独立 bridge 网络,服务通过容器名直接解析,无需依赖 links。
  • depends_on:定义容器之间的依赖顺序,支持 condition: service_started(默认)、service_healthy、service_completed_successfully。
  • healthcheck:在 docker-compose.yml 中通过 test、interval、timeout、retries 等字段定义容器健康检测逻辑。
核心要点:仅使用 depends_on 而不配合健康检查,容器可能在进程启动但端口未就绪时就被下游连接,导致连接失败。推荐组合使用 depends_on: condition: service_healthy 与对应服务的健康检查。

4.2 依赖关系与流程

下图展示典型三层测试环境中的网络、启动顺序与健康检查关系:API 服务等待数据库健康,Web 前端等待 API 健康,服务通过两个自定义网络通信。

依赖启动与健康检查流程 Web Frontend Backend API Database net-front net-backend net-db depends_on depends_on healthcheck: curl /health healthcheck: pg_isready 等待健康 说明: 1. 自定义网络分段隔离(net-front / net-backend / net-db),服务仅通过加入的网络通信。 2. depends_on 控制容器启动顺序,配合 condition: service_healthy 确保服务就绪。 3. 健康检查命令(curl / pg_isready)由 service 自身 healthcheck 块定义。

4.3 实现流程与配置

4.3.1 自定义网络配置

在 docker-compose.yml 的 networks 顶级键下定义,然后在每个 service 的 networks 字段引用。

version: '3.8'

networks:
  net-front:
    driver: bridge
  net-backend:
    driver: bridge
  net-db:
    driver: bridge

4.3.2 依赖启动顺序与健康检查组合

以下配置演示数据库、API、前端三层服务的完整依赖与健康检查设置:

services:
  db:
    image: postgres:15-alpine
    networks:
      - net-db
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

  api:
    image: my-api:latest
    depends_on:
      db:
        condition: service_healthy
    networks:
      - net-backend
      - net-db
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 15s
      timeout: 3s
      retries: 3

  web:
    image: my-web:latest
    depends_on:
      api:
        condition: service_healthy
    networks:
      - net-front
      - net-backend
    ports:
      - "80:80"
注意:depends_on 只是容器启动顺序,不是服务就绪顺序。必须配合 healthcheck 的 condition: service_healthy 才能实际等待端口可用。另外,自定义网络名称不要与系统预留网络名(如 host、none、default)冲突。

4.4 调试与验证

4.4.1 检查网络与容器连接

使用以下命令验证自定义网络和容器连通性:

# 列出所有网络
docker network ls

# 检查某个网络下连接的容器
docker network inspect net-backend

# 进入容器测试解析
docker exec -it api-container ping db-container

# 查看容器健康状态
docker inspect --format='{{.State.Health.Status}}' api-container

4.4.2 查看启动日志中的依赖等待

Compose 在启动时会输出类似以下日志,说明等待上游服务健康:

api  | Waiting for db to be healthy (condition: service_healthy)...
db   | PostgreSQL init process complete; ready for start up.
api  | db is healthy. Starting service...
web  | Waiting for api to be healthy...
api  | Healthcheck succeeded: HTTP 200 /health
web  | api is healthy. Starting nginx...

4.5 常见错误及解决

错误现象 原因 解决方案
服务启动后下游立即连接失败 仅使用 depends_on 未加健康条件 改为 condition: service_healthy 并定义 healthcheck
健康检查一直失败,服务卡住 健康检查命令错误或端口不对 在容器内手动执行 pg_isready 或 curl 验证命令
容器之间无法通过服务名访问 未加入同一自定义网络 检查 service 的 networks 列表,确保依赖双方在同一网络
网络重叠导致 DNS 解析混乱 多个网络中有同名服务 使用唯一服务名,或借助别名 aliases 区分

4.6 性能与稳定性优化建议

  • 合理设置健康检查间隔:interval 不宜过短(<10s),避免占用过多 CPU;数据库类服务可适当延长至 15-30s。
  • 使用 restart: unless-stopped:配合健康检查,当容器不健康但未退出时,Docker 不会自动重启,需结合 restart 策略确保服务恢复。
  • 网络细化隔离:仅将必要服务加入同一网络,减少广播域和安全风险。
  • 避免循环依赖:depends_on 不能形成环,Compose 会报错启动失败。
  • 利用 start_period:在 healthcheck 中设置 start_period: 30s,给容器初始化时间,避免启动初期的误判。
生产实践建议:在测试环境配置中,建议将健康检查与 condition: service_healthy 作为标准写法,避免偶发性连接失败导致测试不稳定。同时,在 CI/CD 中可通过 docker compose up --wait(需 Compose v2)等待所有服务达到健康状态后再执行测试用例。