首页/云/Docker 容器速查/unhealthy 健康检查失败定位
容器排障52 条

unhealthy 健康检查失败定位

unhealthy 是健康检查命令失败:读 inspect 的 Health.Log 看最近几次输出与退出码,手动复现同一命令,再核对 start_period/interval/timeout。

Docker 容器速查云更新于 2026-10-13

unhealthy 意味着什么

健康检查是 Dockerfile 里 HEALTHCHECK 定义的一条命令,退出码为 0 判为健康,其余判为不健康;连续失败达到重试次数后状态变成 unhealthy。它只反映这条命令的结果,不代表服务整体不可用。定位顺序是:先读检查历史的原始输出与退出码,再在容器里手动复现同一条命令,最后核对间隔、超时、重试与启动宽限这几个时序参数。

基本信息

检查历史docker inspect -f '{{json .State.Health}}' 容器
复现方式docker exec 容器 sh -c 同一条检查命令,输出 rc=$?
时序参数interval / timeout / retries / start_period
判定口径退出码 0 才算健康,其余都算失败

典型使用场景

  • 启动即 unhealthy:服务冷启动慢,检查在依赖就绪前就开始跑
  • 偶发 unhealthy 后自愈:上游抖动或超时给得太短,需要调时序参数
  • 编排层反复重建容器:平台按健康状态判定失败并重启,先定位检查本身
  • 发布后健康检查不通过:新版本改了健康检查路径或端口,检查命令没同步
  • 手动能通检查不通:检查命令使用的地址、端口与人工操作不一致

采集证据与复现

采集证据与复现
# 看最近几次检查的输出与退出码
docker inspect -f '{{json .State.Health}}' web | head -c 1500

# 手动复现同一条检查命令,保留退出码
docker exec web sh -c 'curl -fsS http://127.0.0.1:8080/health; echo rc=$?'

# 镜像里没有 curl 时,用 sh 能用的方式重写检查
docker exec web sh -c 'nc -z 127.0.0.1 8080; echo rc=$?'

# 查看镜像里定义的健康检查
docker image inspect app/web:1.4.2 --format '{{json .Config.Healthcheck}}'

常见原因对照

现象原因处理
启动后立刻不健康慢启动但没配启动宽限加 start_period 覆盖冷启动阶段
忽好忽坏上游抖动或超时过短调大 timeout 与 retries
一直不健康检查命令在镜像里不存在改用镜像内可用的工具或检查端口
手动通过、检查失败检查命令指向的地址或端口不同复现时保持与检查完全一致
检查只看命令的退出码:写成管道或重定向时退出码可能来自后一段命令,检查逻辑要避免这种写法。
健康检查失败本身不会终止容器,但编排平台会据此判定不可用并重建,重启循环往往从这里开始。

易错点

  • 检查依赖镜像里没有的工具:curl 或 wget 缺失时永远不健康,改用 sh 与 nc 等基础能力实现
  • 慢启动服务不配启动宽限:容器被反复标记不健康并重启,形成循环
  • 把检查写成复合管道:退出码来自最后一段命令,检查结果与真实状态脱节
  • 只调重试次数不看根因:重试变多只是延后失败,检查路径与端口对不上仍然治不好

数据来源与参考

  • Docker 官方文档:HEALTHCHECK 与 docker inspect Health(docs.docker.com)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌