← 中文资源

简体中文版本

Docker Compose — depends_on 不等待就绪

通过健康检查和基于条件的依赖,加上应用重试,修复应用先于数据库或队列就绪而启动的竞态。

阅读英文原文

启动顺序不等于就绪

depends_on 只保证依赖容器先于应用启动,但依赖可能仍在初始化。例如 PostgreSQL 可能已打开端口,却仍在恢复或创建数据库。应用立刻连接,得到连接拒绝或认证错误。

services:
  db:
    image: postgres:15-alpine
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app -d app"]
      interval: 2s
      timeout: 3s
      retries: 20
  app:
    build: .
    depends_on:
      db:
        condition: service_healthy

让健康检查有意义

健康检查应测试应用真正需要的服务,而不只是进程存在。pg_isready 检查数据库能否接受连接;Redis 的 PING 或 HTTP readiness 端点也比 TCP 端口检查更合适。设置适合最慢启动时间的间隔和重试次数。

应用内也要重试

即使有健康检查,启动后仍可能发生重启或网络抖动。应用应使用有界连接重试、退避和清晰的失败信息。这能抵御编排器差异,并让本地与生产行为一致。

从冷启动验证

执行 docker compose down -v 再 docker compose up,然后不带卷重复一次。确认应用等待健康状态并成功启动。在启动期间停止数据库,验证应用会重试或清晰失败,而不是以难以理解的错误崩溃。

修复与验证

用真实的依赖健康检查、condition: service_healthy 和应用内有界重试修复启动竞态。通过冷卷启动、启动中停止依赖,以及确认应用要么成功等待要么报告可重试错误来验证。固定的 sleep 不算修复,它只改变同一竞态的发生时机。