bigywater.tech
Docker · 70

HEALTHCHECK:状态怎么流转、重试与启动宽限

HEALTHCHECK 的各个参数到底怎么起作用?为什么启动慢的程序会闪一下 unhealthy?unhealthy 的容器会被自动重启吗?这篇用可控的检查命令实测状态变化的时间点。

3.2 → 4.2 秒
启动慢的程序:先 unhealthy(3.2 秒),文件出现后变回 healthy(4.2 秒)
7.1 秒
start-period=6s 时,一直失败的检查变成 unhealthy 的时间(无 start-period 时 2.2 秒)
ExitCode=-1
健康检查命令超时时记录的退出码

状态机与慢启动

实测 · 本机执行输出
  容器 sleep 4 秒后才创建 /tmp/ready,interval=1s:状态变化 starting(0.0s) → unhealthy(3.2s) → healthy(4.2s)
  Health 对象的字段:['FailingStreak', 'Log', 'Status'];FailingStreak=0;最近一次日志:ExitCode=0 Output=''
  docker ps 的 STATUS 列:Up 4 seconds (healthy)

刚启动是 starting;连续失败 retries 次变成 unhealthy;任何一次成功就回到 healthy。docker inspect 的 State.Health 有 Status、FailingStreak 和最近几次的 Log。程序要 4 秒才就绪、检查每秒一次重试 3 次时,容器会在第 3 秒先变成 unhealthy,再在第 4 秒变回 healthy。

一直失败

实测 · 本机执行输出
  --health-cmd "exit 1" interval=1s retries=3:状态变化 starting(0.0s) → unhealthy(3.1s)
  FailingStreak=3;日志条数=3;容器 Status=running(unhealthy 但仍在运行)

连续失败 3 次后约 3.1 秒变成 unhealthy,FailingStreak 记录连续失败次数。容器的 Status 仍是 running,unhealthy 只是标记。

超时

实测 · 本机执行输出
  --health-cmd "sleep 5" --health-timeout 1s retries=1:状态变化 starting(0.1s) → unhealthy(2.1s)
  日志:ExitCode=-1 Output='Health check exceeded timeout (1s)'

超过 --health-timeout 的检查按失败计,日志里 ExitCode=-1,Output 是 Health check exceeded timeout (1s)。

start-period

实测 · 本机执行输出
  start-period=0s(一直失败,retries=2):状态变化 starting(0.1s) → unhealthy(2.2s)
  start-period=6s(一直失败,retries=2):状态变化 starting(0.0s) → unhealthy(7.1s)

用 --health-start-period 让启动阶段的失败不计数:一直失败的检查,start-period 为 0 时 2.2 秒变成 unhealthy,为 6s 时推迟到 7.1 秒。给启动慢的程序设置它,可以避免先闪一下 unhealthy。

不会重启

实测 · 本机执行输出
  --restart always 且健康检查一直失败:RestartCount=0;Status=running;events:create → start → health_status: unhealthy

docker 不会因为 unhealthy 重启容器,即便设了 --restart always。它的作用是被 docker compose 的 depends_on 或外部编排消费。

分步演示

健康检查
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Docker Desktop(Engine 29.8.2,容器跑在 Docker Desktop 自带的 Linux 虚拟机里,内核与宿主机的 macOS 不同);镜像为 linux/arm64;需要看虚拟机内部时用特权容器 + nsenter;计时用 time / date +%s%N,数字每次运行会有小幅抖动。检查命令用 test -f、exit 1、sleep 5 等可控的命令;状态变化时间用 Python 每 0.2 秒轮询 docker inspect 记录,误差约 ±0.3 秒;每种配置运行一次;实验后已删除容器
    • 没有验证:Dockerfile 里的 HEALTHCHECK 指令(与 --health-cmd 等价的部分未对比)、--health-start-interval、真实服务的 HTTP 检查、健康检查本身的 CPU 开销、docker events 里 health_status: healthy 的细节
    京ICP备2026067502号-1京公网安备11010502063487号