别再用 sleep 10 了:用 Docker Compose healthcheck 解决“容器起来了但服务没就绪”

举报
yd_241226763 发表于 2026/10/30 16:36:15 2026/10/30
【摘要】 很多同学在本地跑 docker compose up 时都会遇到一个现象:容器状态已经是 Up,应用却连不上。翻一遍日志才发现,数据库还在初始化、后端还在跑迁移。于是有人在启动脚本里塞一串 sleep 10,似乎能用,但它解决的是「等多久」,不是「等什么」。真正的解法是让编排器知道服务到底有没有就绪,这就是 healthcheck。 一、healthcheck 到底在做什么它是一条在容器内部...

很多同学在本地跑 docker compose up 时都会遇到一个现象:容器状态已经是 Up,应用却连不上。翻一遍日志才发现,数据库还在初始化、后端还在跑迁移。于是有人在启动脚本里塞一串 sleep 10,似乎能用,但它解决的是「等多久」,不是「等什么」。

真正的解法是让编排器知道服务到底有没有就绪,这就是 healthcheck。

一、healthcheck 到底在做什么

它是一条在容器内部周期性执行的命令。退出码 0 表示健康,1 表示不健康。Docker 根据最近若干次结果,给容器打上 starting 或 healthy 标记。注意是容器内部执行,所以命令必须存在于镜像里,你要保证 curl、wget 或对应客户端已经装好——不少 slim 镜像里没有 curl,这是最常见的坑。

services:
  api:
    image: my-api:1.0
    healthcheck:
      test: ["CMD-SHELL", "curl -fsS http://localhost:8080/health || exit 1"]
      interval: 10s
      timeout: 3s
      retries: 5
      start_period: 30s

几个参数值得单独说:interval 是探测间隔;retries 表示连续失败几次才判定 unhealthy;start_period 经常被忽略,它给了一段「免责期」,期间失败只算 starting,不计入重试次数,正好用来覆盖迁移、预热这类慢启动场景。没有它,慢启动服务很容易在起来之前就被判死。

二、depends_on 也要跟着升级

很多人以为写了 depends_on 就等于等服务就绪,其实它默认只保证「容器被创建」。要依赖健康状态,得用长语法:

  web:
    image: nginx:alpine
    depends_on:
      api:
        condition: service_healthy

这样 Compose 会先让 api 达到 healthy,再启动 web。数据库依赖——Postgres 用 pg_isready,MySQL 用 mysqladmin ping,Redis 用 redis-cli ping——同理:

  db:
    image: postgres:16
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app -d app"]
      interval: 5s
      timeout: 3s
      retries: 10
      start_period: 20s

三、/health 接口本身别写成摆设

最常见的错误是把健康检查写成只返回一个 200 的空接口,那样它和 TCP 探活没区别。一个合格的实现至少要碰一下真实依赖:查一条 SELECT 1,或者读一次磁盘上的关键目录。代价很低,但能在连接池阻塞、磁盘写满这类「进程还活着,服务已经废了」的故障里提前暴露问题。反过来也要注意别在探测里做重操作——健康检查每秒可能有多次,别把它变成压力源。

四、排查 unhealthy

容器被打上 unhealthy 后,用 docker inspect --format '{{json .State.Health}}' <容器名> 看最后几条输出的 Log 字段,命令的报错内容就写在里面。多数情况不外乎两类:命令不存在,或者容器里压根监听在别的端口。

小结

把 sleep 10 换成 healthcheck,本质上是从「猜一个时间」变成「声明一个条件」。改动不大,一个下午就能把整套 Compose 文件改完,但它消除的是一整类只在 CI 上偶发、本地却复现不了的玄学失败,值得。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。