depends_on 仅控制容器启动顺序,不保证服务就绪;需配合 healthcheck 和 condition: service_healthy 实现真正就绪等待,或用 wait-for-it.sh 脚本探测端口。

depends_on 不能真正控制服务“就绪”,只能保证容器进程已启动。如果你发现 web 容器一启动就报 Connection refused,大概率是误把“容器运行”当成了“服务可用”。
depends_on 只管容器启动,不管服务就绪
这是最常踩的坑。Docker Compose 的 depends_on 仅向 Docker daemon 发送启动顺序指令,不执行任何连接检测或状态等待。
-
depends_on: - db表示:等db容器Created → Running状态切换完成,就立刻启动当前服务 - PostgreSQL 容器可能已运行,但
pg_isready还返回no response;MySQL 可能还在初始化系统表 - 健康检查(
healthcheck)默认不启用,depends_on也不会自动读取它
condition: service_healthy 是唯一官方支持的就绪等待方式
从 Compose 文件格式 v2.1 起,depends_on 支持带条件的依赖声明,必须配合 healthcheck 才生效。
- 数据库服务必须显式定义
healthcheck,例如:test: ["CMD-SHELL", "pg_isready -U postgres"] - 依赖方需写成:
depends_on: db: condition: service_healthy(注意缩进和冒号后空格) - 若健康检查失败,
web会一直阻塞,直到db连续通过retries × interval次检测 - 不支持
service_started以外的条件(如service_completed_successfully)
wait-for-it.sh 是最轻量、兼容性最好的 fallback 方案
当无法修改目标服务(如用第三方镜像且没配 healthcheck),或需要更细粒度控制重试逻辑时,用脚本主动探测端口最直接。
- 下载脚本:
curl -o wait-for-it.sh https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh - 给执行权限:
chmod +x wait-for-it.sh - 挂载并改
command:command: ["sh", "./wait-for-it.sh", "db:5432", "--timeout=60", "--", "npm", "start"] - 注意:
wait-for-it.sh只检测 TCP 连通性,不验证协议层(比如 Redis 的PING或 HTTP 的200 OK)
别信“docker-compose.yml 里服务书写顺序决定启动顺序”
这是过时认知。自 Compose v2 起,启动顺序完全由 depends_on 图谱决定,与 YAML 中 services 的排列顺序无关。
- 即使你把
web写在db前面,只要web.depends_on包含db,db就一定先启动 - 没有
depends_on的服务,默认并行启动,顺序不可预测 - 循环依赖(A → B → A)会导致
docker-compose up直接报错:Service 'A' is part of a circular dependency with 'B'
实际部署中,最容易被忽略的是健康检查的 timeout 和 retries 配合。比如 PostgreSQL 初始化可能耗时 20 秒,但若你设 timeout: 2s + retries: 3,总共只等 6 秒就放弃,service_healthy 永远不会达成。











