Docker 容器的健康检查 HEALTHCHECK 指令

FreeGuideOnline 最新 2026-07-07

dockerfile HEALTHCHECK [选项] CMD <命令>


**2. 禁止从基础镜像继承:**
```dockerfile
HEALTHCHECK NONE

如果基础镜像中已经定义了健康检查,而你希望当前镜像取消它,则使用 NONE

常用选项(均可选,括号内为默认值):

  • --interval=DURATION:检查间隔,默认 30s
  • --timeout=DURATION:单次检查命令的超时时间,默认 30s
  • --start-period=DURATION:容器启动后等待开始健康检查的时间(此时检查失败不计入重试次数),默认 0s
  • --start-interval=DURATION:在启动期间(start period 内)检查的间隔,用于快速探测,Docker 25.0+ 支持,默认 5s
  • --retries=N:连续失败多少次后状态变为 unhealthy,默认 3 次。

CMD 后面的命令会在容器内部执行,通过退出码报告健康状态:

  • 0:成功 → 容器健康。
  • 1:不健康 → 容器运行异常。
  • 2:保留值,尽量不使用此退出码(部分旧版本可能会误判)。

注意:健康检查命令不能占用过多资源,执行时长应小于 timeout;应使用轻量级工具(如 curlmysqladmin、自定义脚本)快速探测。

编写你的第一个健康检查

假设我们运行一个 Nginx 服务,希望确认其 Web 服务可用。

FROM nginx:alpine
# 每隔 10 秒使用 curl 检查本地首页,超时 5 秒,启动后等待 30 秒再开始检查
HEALTHCHECK --interval=10s --timeout=5s --start-period=30s --retries=3 \
  CMD curl -f http://localhost/ || exit 1

解释:

  • curl -f:如果服务器返回 HTTP 错误码(如 404、500),-f 会让 curl 以非零退出码退出,触发健康失败。
  • || exit 1:确保非零退出码被捕获,使 Docker 明确收到失败信号。

构建并运行容器后,可通过 docker psdocker inspect 查看健康状态。

docker build -t my-nginx-health .
docker run -d --name web my-nginx-health
docker ps

输出示例:

CONTAINER ID   IMAGE               ...   STATUS                   
a1b2c3d4e5f6   my-nginx-health      ...   Up 10 seconds (healthy)

常用健康检查命令示例

针对 Web 应用

HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://127.0.0.1:8080/health || exit 1

针对 MySQL 数据库

FROM mysql:8.0
HEALTHCHECK --interval=20s --timeout=5s --retries=3 \
  CMD mysqladmin ping -h localhost -u root --password=$MYSQL_ROOT_PASSWORD || exit 1

针对 Redis

FROM redis:alpine
HEALTHCHECK --interval=15s --timeout=3s \
  CMD redis-cli ping || exit 1

使用自定义脚本

当某个简单的命令无法满足逻辑时,可以编写 shell 脚本:

COPY healthcheck.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/healthcheck.sh
HEALTHCHECK --interval=30s --timeout=10s CMD /usr/local/bin/healthcheck.sh

healthcheck.sh 内容示例:

#!/bin/sh
# 检查某个关键文件是否存在,并确认进程监听端口
if [ -e /tmp/app.ready ] && netstat -tlnp | grep 3000 > /dev/null; then
    exit 0
else
    exit 1
fi

查看和管理容器健康状态

1. 使用 docker ps

STATUS 列会显示 (healthy)(unhealthy)(health: starting)(在 start-period 或重试之前)。

2. 使用 docker inspect

获取详细的健康检查日志:

docker inspect --format='{{json .State.Health}}' <container> | jq

返回的 JSON 包含:

  • Status"healthy", "unhealthy", "starting"
  • FailingStreak:当前连续失败次数
  • Log:最近几次检查的详细输出(命令、时间、退出码、输出)

示例日志条目:

"Log": [
  {
    "Start": "2025-01-01T12:00:00.123456789Z",
    "End": "2025-01-01T12:00:00.456789123Z",
    "ExitCode": 0,
    "Output": "<response from curl...>"
  }
]

3. 根据健康状态过滤容器

docker ps --filter "health=healthy"
docker ps --filter "health=unhealthy"

4. 强制触发一次即时健康检查

Docker 不支持手动触发,但你可以使用 docker exec <container> <healthcheck-command> 手动执行相同的命令进行测试。

进阶:启动周期与间隔优化

--start-period 对启动缓慢的应用至关重要(例如 Java 应用、需要预热缓存的数据库)。此期间内,即使检查失败也不会增加失败计数,直到应用真正就绪。例如:

HEALTHCHECK --start-period=60s --start-interval=10s --interval=30s --timeout=5s CMD ...
  • 启动前 60 秒内,每 10 秒检查一次(启动间隔)。
  • 60 秒后,恢复为每 30 秒一次。

注意--start-interval 在 Docker 25.0 中引入,旧版本不支持,会报错。请根据 Docker 版本选择使用。

编排中的健康检查行为

Docker Swarm 模式

在服务编排中,当某个副本的健康状态变为 unhealthy 后,Swarm 会自动重启该任务(容器),确保服务的期望副本数始终健康。

docker service create --name my-service --replicas 3 --health-cmd="curl -f http://localhost/" ...

Docker Compose

docker-compose.yml 中,通过 healthcheck 字段定义,与 Dockerfile 指令完全对应:

services:
  web:
    image: my-web
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s