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 容器启动后再启动 a1.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 composeCLI。如果版本太旧,只支持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 状态如果没有给 nginx 配 healthcheck,service_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: 5VastBase 是 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: 53.4 Redis
healthcheck:
test: ["CMD-SHELL", "redis-cli ping | grep PONG || exit 1"]
interval: 5s
timeout: 3s
retries: 53.5 MongoDB
healthcheck:
test: ["CMD-SHELL", "mongosh --eval 'db.adminCommand({ ping: 1 })' || exit 1"]
interval: 10s
timeout: 5s
retries: 53.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 / VastBase | 5432 | pg_isready / nc -z 5432 |
| Oracle | 1521 | sqlplus / nc -z 1521 |
| MySQL | 3306 | mysqladmin ping / nc -z 3306 |
| Redis | 6379 | redis-cli ping / nc -z 6379 |
| MongoDB | 27017 | mongosh --eval / nc -z 27017 |
核心原则:用什么数据库,就用它的原生客户端做探测,最准确。没有客户端再用 nc 或 /dev/tcp 做端口探测兜底。
评论 (0)