Docker 健康检查的目的、影响和处理
前言
网上关于 Docker 的教程往往只会讲容器、镜像、网络、数据卷。对于健康检查往往只是一笔带过:在 Dockerfile 中写一个 HEALTHCHECK 命令,然后看到容器状态变成了 “healthy” 就万事大吉。而对于不健康的容器会造成什么影响、如何处理不健康的容器则很少提及。
如果想充分发挥容器化的健壮性优势,我们就需要认真审视 Docker 提供的健康检查功能。
结论先行
Docker 健康检查是保障容器化应用可靠性的关键机制。 不健康的容器会被 Docker 网络自动隔离,但 Docker 本身不会重启它们。我们需要结合 autoheal 工具实现自动重启,并通过 Prometheus + Alertmanager 实现告警监控。
为什么需要健康检查?
默认检查方式的局限性
默认情况下,Docker 判断一个容器是否存活的方式是通过检测容器内 PID = 1 的进程是否存活(这个进程就是 Dockerfile 的 ENTRYPOINT 中启动的进程)。
这个检查方式非常粗放,因为有时容器已经失去了正常对外提供服务的能力,但是进程仍然存活。例如:
- 应用陷入死锁,无法响应请求
- 数据库连接池耗尽,无法处理新请求
- 内存泄漏导致 GC 频繁,响应缓慢
用户自定义健康状态
鉴于以上的情况,容器的健康状态应该由用户定义。
常见的检测方案:
应用本身暴露一个 HTTP 接口,用于表示自己是否健康,然后通过定时检查访问该接口来判断应用的健康状态。
示例:Spring Boot Actuator 提供的 /actuator/health 端点。
这样,我们就可以准确判断哪些容器是健康的,哪些是不健康的。
当一个容器不健康时,会发生什么?
Docker 网络的自动隔离
我们知道,处于同一个 Docker 网络中的容器可以通过容器名代替 DNS 名称进行互相访问。容器名会被解析为对应的 IP 地址。
关键机制:
在进行 DNS 解析时,不会返回不健康的容器的 IP,DNS 解析会因为得不到正常结果而失败。
你可以认为这是 Docker 实现的**”服务熔断”**:不健康的容器不允许提供服务。
对反向代理的影响
如果这是一个被反向代理(使用 Traefik 或 Nginx Proxy Manager)的 HTTP 服务,你会发现服务无法访问,这是因为网关无法访问到不健康的容器。
如何处理不健康的容器?
Docker 的默认行为
重要:Docker 不会对 unhealthy 状态的容器进行任何处理。
自动重启方案:docker-autoheal
我们的常见思路是重启,但是这要依赖另一个开源软件:
项目地址:https://github.com/willfarrell/docker-autoheal
工作原理:
这个软件非常简单,只需要挂载 Docker socket 文件,即可自动检查并重启不健康的容器。
使用示例:
1 | version: '3' |
告警监控方案
当然,一些故障是重启无法解决的,必须要人工介入。我们可以使用 Prometheus + Alertmanager 的方式及时发现服务异常并告警。
告警方式:
- 邮件
- Webhook
- 各种机器人(钉钉、企业微信、Slack 等)
总结
| 主题 | 核心要点 |
|---|---|
| 健康检查的必要性 | 默认的进程存活检查不够准确,需要用户自定义 |
| 不健康容器的影响 | Docker 网络会自动隔离,DNS 解析失败 |
| 自动重启 | 使用 docker-autoheal 工具 |
| 告警监控 | 使用 Prometheus + Alertmanager |
Docker 健康检查机制是容器化应用可靠性的重要保障。通过合理配置健康检查、自动重启和告警监控,可以大大提升系统的稳定性和可用性。




