报数据库连不上?Docker Compose 启动顺序假象:depends_on 不是万能的!

2 阅读1分钟

📖 背景 服务器重启后。大屏(Flask)总是报错 Connection refused。看日志:Can't connect to MySQL server on 'db'。 执行 docker compose up -d 也是一样。明明写了 depends_on: - db。db 容器明明在运行。

🔍 原因 小学生版解释: depends_on 就像比赛时的“排队”。它只保证跑道上 db 先跑,dashboard 后跑。 但 db(MariaDB)是个大胖子。跑到起跑线后,还要花 5 秒系鞋带(初始化数据库、监听端口)。 dashboard 跑得飞快,起跑后直接敲门,发现 db 还没弄好,立刻报错退出。

🛠 解决 不能用 depends_on。要用 healthcheck(健康检查)+ condition: service_healthy。 修改 docker-compose.yml:

services:
  db:
    image: mariadb
    healthcheck:
      # 只要 docker 内执行该命令成功,才算健康
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 5s
      timeout: 3s
      retries: 5

  dashboard:
    image: flask-app
    depends_on:
      db:
        condition: service_healthy # 关键:等 db 健康了再启动

改完执行 docker compose up -d 重建。

✅ 验证效果 用 docker ps 观察。 注意看 STATUS 这一列:db 变成 Up (healthy) 之前,dashboard 会显示 Created 或 Waiting。一旦 db 变绿(healthy),dashboard 才会启动。 大屏不报错了。

💣 三个坑 老版本 Compose 不认:如果你的 docker compose 版本很老(V2 以下),可能不支持 condition: service_healthy,必须升级 compose 插件。

健康检查命令写错:test 里的命令如果没有指定 CMD 或者写错,容器永远 unhealthy,导致后端永远起不来。

不写超时退出:如果不配合 restart: always(重启策略),一旦后端起太快报错退出,它就不会自己重试了。