
这篇指南教你为 Docker(一种把应用和依赖打包成容器的虚拟化技术)容器配置健康检查与自动恢复,用 HEALTHCHECK 指令和 restart 策略搭建一套能自动发现故障并拉起服务的机制。容器能启动不等于服务健康,进程还在但接口无响应的情况,恰恰是最难排查的问题。
一、理解 HEALTHCHECK 的作用
默认情况下,Docker 只关注容器主进程是否在运行,只要进程没退出就认为容器正常。但很多故障是”假死”:进程存活、端口在监听,实际业务逻辑已经卡死。HEALTHCHECK 指令让 Docker 周期性执行一条命令,根据命令退出码判断容器是否健康。退出码 0 表示健康,1 表示不健康,其余为检查失败。
# 健康检查命令示例,每 30 秒检查一次 HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ CMD curl -fs http://localhost:8080/health || exit 1
上面的例子每 30 秒请求一次健康接口,超时 5 秒,连续 3 次失败即判定不健康。容器状态会从 healthy 变成 unhealthy。合理配置这些参数能避免误判,例如慢启动的应用需要更长的 start-period,避免在服务尚未就绪时就因为检查失败被反复重启。
二、在 Dockerfile 与 Compose 中配置
HEALTHCHECK 既可以直接写在 Dockerfile 里作为镜像的默认配置,也可以在 docker compose(用 YAML 文件定义多容器应用的工具)中为单个服务覆盖。在 Compose 里配置更灵活,方便针对不同环境调整检查频率。
services:
web:
image: myapp:latest
healthcheck:
test: ["CMD", "curl", "-fs", "http://localhost:3000/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 20s
restart: unless-stopped
健康检查命令必须在容器内可用。很多精简镜像没有 curl(用于通过命令行发送 HTTP 请求的工具),这时可以用镜像自带的 wget,或用 Python、Node 等运行时提供的请求能力。写检查命令时优先选择应用自身的健康接口,而不是只探测端口,因为端口响应不等于业务正常。
三、用 restart 策略实现自动恢复
健康检查本身不触发重启,自动恢复由 restart(重启)策略负责。Docker 支持 no、on-failure、always、unless-stopped 四种策略。要同时实现”不健康即重启”,单靠 restart 策略不够,因为 restart 针对的是进程退出,而非健康状态。生产环境中常用外部编排器或监控在检测到 unhealthy 后主动重启容器。
# 查看容器健康状态
docker ps
# 查看健康检查最近输出
docker inspect --format='{{json .State.Health}}' <容器名>
在单机 Docker 环境,可以结合 cron 脚本定期检查容器健康状态并执行重启,或引入轻量监控在检测到 unhealthy 时调用 docker restart。无论哪种方式,都要加上失败重试上限与告警,防止容器因配置错误陷入重启循环,把问题从”假死”变成”反复重启”。若你在排查重启循环或日志异常增长,可参考MySQL 慢查询分析的思路,先确认写入与依赖来源再定位根因。

四、让编排器接管健康检查
如果运行环境支持编排,把健康检查与自动恢复交给 Docker Swarm 或 Kubernetes 更可靠。编排器会把不健康的容器摘除流量并重建新实例,实现比单机 restart 更完整的自愈。健康检查的退出状态会反馈给调度器,用于决策是否需要替换实例。
# Docker Swarm 服务健康检查 docker service create --name web --health-cmd "curl -fs http://localhost:3000/health" \ --health-interval 30s --health-timeout 5s --health-retries 3 \ --replicas 2 myapp:latest
编排器模式下,健康检查还承担了流量路由的作用,只有 healthy 的副本才会接收请求。这比单纯的进程存活检测更能反映真实可用性。对于追求高可用的服务,建议健康接口返回时带上依赖状态(如数据库连接是否正常),让流量只进入真正可用的实例。
五、健康接口的设计要点
健康接口本身的设计决定了检查是否有意义。一个合格的健康接口应快速返回,不依赖外部服务,并区分存活与就绪。存活(liveness)只表明进程未崩溃,就绪(readiness)才表明可以接收流量。对外健康接口若依赖数据库,在数据库抖动时会导致整体被判定不健康并触发重启。
实践中常把健康接口拆成两类:轻量存活检查用于容器级判定,深度检查用于依赖可用性。重启策略主要基于存活检查,避免因数据库短暂不可用就频繁重启业务容器。数据库这类有状态组件的恢复涉及持久化与缓存一致性,相关概念可参考Redis 持久化与恢复,理解数据落盘时机再设计重启后的数据恢复流程。
六、健康检查的监控与日志
健康检查结果应该进入监控体系,而不只是在 Docker 内部可见。把 docker events 或健康状态变化上报到监控平台,可以在容器变不健康的第一时间收到告警,而不必等到用户反馈。定时抓取健康状态并记录,能还原故障发生的准确时间线。

# 监听容器事件,识别健康状态变化 docker events --filter event=health_status
日志层面,健康检查命令的输出会保留在容器元数据中,可用 docker inspect 查看最近几次检查的返回。结合应用自身的访问日志,可以判断健康检查请求是否到达、接口是否真实响应。若你已在搭建统一监控面板,可参考Grafana 服务器部署实践,把容器健康状态与主机指标一起呈现,便于观察故障关联性。
七、面向网络与流量的健康检查
对于暴露公网的容器,健康检查还应考虑网络路径。容器内健康不等于外部可访问,反向代理或防火墙可能拦截请求。可在部署后从外部拨测验证,确认健康接口在真实用户路径上可达。这类排查常涉及连接与限流设置,可参考Nginx 限流配置理解请求频率与连接限制如何影响健康探测。
证书续期后重启容器或重新加载配置,也需要配合健康检查确认服务恢复,避免重启后接口处于异常状态却未触发检查。关于证书相关服务的重启与验证,可参考certbot 证书续期排错中的验证流程。
总结
Docker 容器健康检查的正确配置包含三个层次:用 HEALTHCHECK 定义有意义的健康判定,用 restart 或编排器实现自动恢复,再把健康状态接入监控与告警。关键在于区分进程存活与业务就绪,避免用单一端口探测掩盖真实故障。对于 Hostease 这类面向中文用户的 [VPS](https://cn.hostease.com/vps/)([虚拟专用服务器](https://cn.hostease.com/vps/),Virtual Private Server)与[独立服务器](https://cn.hostease.com/dedicated-server/)环境,把容器健康检查与监控、日志体系配合起来,能显著降低服务”假死”带来的不可用时间。