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 |
| 一直不健康 | 检查命令在镜像里不存在 | 改用镜像内可用的工具或检查端口 |
| 手动通过、检查失败 | 检查命令指向的地址或端口不同 | 复现时保持与检查完全一致 |
检查只看命令的退出码:写成管道或重定向时退出码可能来自后一段命令,检查逻辑要避免这种写法。
健康检查失败本身不会终止容器,但编排平台会据此判定不可用并重建,重启循环往往从这里开始。