Docker 容器一直显示 unhealthy:从 Healthcheck 输出到依赖故障的完整排查

容器进程仍在运行,docker ps 却显示 unhealthy。这表示主进程没有退出,但镜像定义的健康检查连续失败。此时负载均衡器或编排系统可能停止向容器转发流量,业务依然会表现为不可用。

一、先读取健康检查结果

bash 复制代码
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Image}}'
docker inspect <container> --format '{{json .State.Health}}'

更易阅读的方式:

bash 复制代码
docker inspect <container> \
  --format '{{range .State.Health.Log}}{{.Start}} exit={{.ExitCode}} {{printf "%s" .Output}}{{println}}{{end}}'

重点看最近几次检查的退出码、输出和执行时间。unhealthy 只是结果,真正原因通常已经写在 Output 中。

二、确认镜像定义了什么检查

bash 复制代码
docker inspect <container> --format '{{json .Config.Healthcheck}}'

常见检查是访问 HTTP 健康接口:

dockerfile 复制代码
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
  CMD curl -fsS http://127.0.0.1:8080/health || exit 1

需要核对端口、路径、协议和工具是否真的存在。精简镜像中可能没有 curl,应用也可能已经改了端口,但 Dockerfile 仍保留旧配置。

三、在容器内部复现命令

bash 复制代码
docker exec -it <container> sh

进入后执行 Healthcheck 的原始命令,并检查:

bash 复制代码
ps aux
ss -lntp 2>/dev/null || netstat -lntp
curl -v http://127.0.0.1:8080/health

如果镜像不包含 shell 或诊断工具,可以使用同网络命名空间的临时调试容器,避免为了排障直接修改生产镜像。

四、区分应用未就绪和依赖故障

健康接口失败不一定是应用进程崩溃,还可能是数据库、Redis、DNS 或外部 API 不可用。

检查容器日志:

bash 复制代码
docker logs --since 30m --tail 300 <container>

检查网络和 DNS:

bash 复制代码
docker exec <container> getent hosts database
docker exec <container> sh -c 'nc -vz database 5432'

如果健康接口把所有外部依赖都设为强制条件,一次短暂的第三方波动就可能把正常应用摘出流量。应区分存活检查与就绪检查:存活检查回答"进程是否需要重启",就绪检查回答"当前是否适合接收流量"。

五、检查超时和启动宽限期

启动较慢的 Java、AI 推理或数据库服务,可能在初始化期间被过早判定失败。合理配置 start_period:

yaml 复制代码
services:
  api:
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8080/health"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 60s

不要盲目把超时改得很长。先测量健康接口正常和异常时的响应时间,再确定参数。

六、验证修复

更新镜像或 Compose 配置后重新创建容器:

bash 复制代码
docker compose up -d --build
docker ps --format 'table {{.Names}}\t{{.Status}}'
docker inspect <container> --format '{{.State.Health.Status}}'

继续观察多个检查周期,并从宿主机或上游代理验证真实请求:

bash 复制代码
curl -fsS http://127.0.0.1:<published-port>/health
docker logs --since 10m <container>

只有状态持续为 healthy、业务请求正常、错误日志不再增长,才算完成修复。

总结

排查 Docker unhealthy 的顺序是:读取 .State.Health.Log,确认 Healthcheck 定义,在容器内部复现命令,检查应用日志和依赖,再调整超时与启动宽限期。不要把删除 Healthcheck 当作修复;那只会让真实故障失去可见性。

相关推荐
沫璃染墨5 小时前
从零入门计算机网络系列(十八):TCP连接管理详解——从三次握手与四次挥手到TIME_WAIT机制
运维·服务器·网络·c++·网络协议·tcp/ip·tcp
Felven6 小时前
华为鲲鹏920s芯片serdestool工具使用说明
linux·运维·服务器·华为·鲲鹏920·serdestool
江湖有缘6 小时前
Docker实战 | 使用Docker部署lemonitor镜像站点列表程序
运维·docker·容器
莫晓燚6 小时前
mall 电商项目完整部署---实战
linux·运维·docker·容器
爱和冰阔落6 小时前
【Linux网络】JsonCpp 怎么实现序列化?从 Request/Response 到网络计算器消息设计
linux·运维·网络·php
Decay__6 小时前
01_SQLServer 体系架构全解 —— 实例进程、关系引擎、SQLOS 与事务日志深入
运维·数据库·sql·mysql·架构
我是koten12 小时前
【运维杂谈】K8s遇到Terminating的名称空间删除不了怎么办?(解决方案亲测有效)
linux·运维·服务器·云原生·kubernetes·k8s·名称空间
修己xj20 小时前
服务器无法解析域名?一次 DNS 配置缺失的排查与修复
运维
xbzb1 天前
自定义 yum 软件源:Linux 上 createrepo,Windows 上纯 Python 也能造
linux·运维·windows·python·yum·createrepo
Android系统攻城狮1 天前
Linux FFmpeg深度解析之avio_open调用流程与实战(三十八)
linux·运维·服务器·ffmpeg·音视频进阶·ffmpeg音视频