Docker Compose 链式依赖启动(depends_on)

奥黛丽·逐爱者
2026-08-06 / 0 评论 / 2 阅读 / 正在检测是否收录...

1.1 基础用法

docker-compose.yml 中使用 depends_on 控制服务启动顺序。

示例:严格链式启动(c → b → a)

version: '3.8'
services:
  c:
    image: nginx:20260805
    container_name: nginx
    # 无依赖,最先启动
  b:
    image: some_service:latest
    depends_on:
      c:
        condition: service_started  # 等 c 容器启动后再启动 b
  a:
    image: ixjkj/tomcat9-jdk8:1.0
    container_name: tomcat9-jdk8
    depends_on:
      b:
        condition: service_started  # 等 b 容器启动后再启动 a

1.2 链式依赖 vs 并列依赖

写法效果
a depends_on: [b, c]b 和 c 同时启动,都就绪后才启动 a
b depends_on: c + a depends_on: b串行:先 c → 再 b → 最后 a

1.3 condition 详解

depends_on:
  service_name:
    condition: service_started              # 容器启动即可(默认)
    # condition: service_healthy            # 等健康检查通过(推荐用于数据库/服务)
    # condition: service_completed_successfully  # 等容器运行结束且 exit 0(用于初始化任务)
condition前提条件等待时机适用场景
service_started(默认)容器启动即可简单依赖,不关心服务是否就绪
service_healthy必须配置 healthcheck健康检查通过数据库、API 服务等需要真正就绪
service_completed_successfully容器运行结束且 exit 0一次性初始化/迁移任务
注意service_healthy 需要 Docker Compose v2.20+ 或较新的 docker compose CLI。如果版本太旧,只支持 depends_on: [service_name](仅等待容器启动)。

2.1 参数含义

healthcheck:
  test: ["CMD-SHELL", "curl -f http://localhost:8086/actuator/health || exit 1"]
  interval: 5s      # 每隔 5 秒检查一次
  timeout: 3s       # 单次检查最多等 3 秒,超时就当这次失败
  retries: 5        # 连续失败 5 次后,容器状态标记为 unhealthy
参数作用示例值
test执行什么命令来判断健康curl 请求接口,成功返回 0,失败返回 1
interval检查频率5s = 每 5 秒查一次
timeout单次检查超时3s = 命令 3 秒没响应就视为失败
retries容错次数5 = 连续失败 5 次才判为 unhealthy

2.2 状态流转

容器启动
   ↓
第一次检查(interval 后)→ 成功 → healthy ✅
   ↓
失败(但 < retries 次)→ 继续检查
   ↓
连续失败 retries 次 → unhealthy ❌

2.3 service_healthy 的前提

condition: service_healthy 必须配合被依赖服务的 healthcheck 使用。

services:
  nginx:
    image: nginx:20260805
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:8086 || exit 1"]
      interval: 5s
      timeout: 3s
      retries: 5

  tomcat:
    image: ixjkj/tomcat9-jdk8:1.0
    depends_on:
      nginx:
        condition: service_healthy   # ← 读取 nginx 的 healthcheck 状态

如果没有给 nginxhealthcheckservice_healthy 会报错或永远等待。

2.4 service_completed_successfully

这是给一次性任务用的,不是持续运行的服务。

典型场景:数据库初始化

services:
  init-db:  # 一次性任务,跑完就退出
    image: postgres:15
    command: ["sh", "-c", "psql -h db -U postgres -f /init.sql"]
    depends_on:
      db:
        condition: service_healthy

  app:  # 主应用,等初始化完成后再启动
    image: myapp
    depends_on:
      init-db:
        condition: service_completed_successfully  # 等 init-db 容器退出且 exit code = 0
问题答案
是等容器关闭吗?是的,等容器运行结束并退出
退出码必须是 0 吗?是的,只有成功完成(exit 0)才算通过
如果 exit 1 呢?depends_on 会判定失败,不会启动下游服务
适合什么场景?数据迁移、初始化脚本、备份任务等跑完就停的容器

数据库不是 HTTP 服务,不能用 curl,要用各自的客户端命令TCP 端口探测

3.1 PostgreSQL / VastBase(兼容 PG)

healthcheck:
  test: ["CMD-SHELL", "pg_isready -U postgres -d your_database"]
  interval: 10s
  timeout: 5s
  retries: 5

VastBase 是 PG 兼容的,所以用 pg_isready。如果镜像里没有该命令,用 psql

psql -U postgres -d your_database -c "SELECT 1" || exit 1

3.2 Oracle

healthcheck:
  test: ["CMD-SHELL", "sqlplus -s / as sysdba <<< 'SELECT 1 FROM DUAL;' || exit 1"]
  interval: 30s
  timeout: 10s
  retries: 5

如果镜像精简没有 sqlplus,用 TCP 端口探测

bash -c 'cat < /dev/null > /dev/tcp/localhost/1521' || exit 1

3.3 MySQL / MariaDB

healthcheck:
  test: ["CMD-SHELL", "mysqladmin ping -h localhost -u root -p$$MYSQL_ROOT_PASSWORD || exit 1"]
  interval: 10s
  timeout: 5s
  retries: 5

3.4 Redis

healthcheck:
  test: ["CMD-SHELL", "redis-cli ping | grep PONG || exit 1"]
  interval: 5s
  timeout: 3s
  retries: 5

3.5 MongoDB

healthcheck:
  test: ["CMD-SHELL", "mongosh --eval 'db.adminCommand({ ping: 1 })' || exit 1"]
  interval: 10s
  timeout: 5s
  retries: 5

3.6 通用兜底:TCP 端口探测

如果镜像精简到没有客户端命令,可以用 nc(netcat)或 Bash 内置的 /dev/tcp

healthcheck:
  test: ["CMD-SHELL", "nc -z localhost 5432 || bash -c 'cat < /dev/null > /dev/tcp/localhost/5432' || exit 1"]
  interval: 10s
  timeout: 5s
  retries: 5
数据库端口推荐命令
PostgreSQL / VastBase5432pg_isready / nc -z 5432
Oracle1521sqlplus / nc -z 1521
MySQL3306mysqladmin ping / nc -z 3306
Redis6379redis-cli ping / nc -z 6379
MongoDB27017mongosh --eval / nc -z 27017

核心原则:用什么数据库,就用它的原生客户端做探测,最准确。没有客户端再用 nc/dev/tcp 做端口探测兜底。

0

评论 (0)

取消