欢迎光临
我们一直在努力

Docker Compose healthcheck 怎么配置?容器健康检查教程

1. Docker healthcheck 是什么?

运行 Docker 容器时,我们经常通过:

docker ps

查看容器状态。

例如:

Up 5 minutes

很多人看到 Up 就认为应用已经能够正常提供服务。

实际上:

容器正在运行,并不等于容器内部的应用一定正常。

例如一个 Web 容器的主进程还在运行,但可能已经出现:

数据库连接失败;

接口无法响应;

应用初始化失败;

依赖服务不可用;

内部端口没有正常提供服务。

Docker 的 healthcheck 就是用来进一步判断:

容器内部的应用是否真正处于健康状态。

配置完成以后,容器可能出现:

starting

healthy

unhealthy

等健康状态。

2. Running 和 healthy 有什么区别?

Docker查看容器healthy和unhealthy健康状态

例如执行:

docker ps

可能看到:

web   Up 3 minutes (healthy)

这里:

Up 3 minutes

表示容器主进程正在运行。

healthy

表示 Docker 设置的健康检查命令已经通过。

另一个容器可能显示:

api   Up 3 minutes (unhealthy)

这说明:

容器主进程仍然存在,但连续多次健康检查失败。

因此在实际项目中:

Running 更偏向“进程还活着”,healthy 更偏向“应用真的能正常工作”。

3. Docker Compose healthcheck 基本配置

Docker Compose配置healthcheck容器健康检查

例如有一个 Web 应用监听:

8080

可以在 compose.yaml 中增加:

services:
  web:
    image: example/app:latest
    restart: unless-stopped
    ports:
      - "8080:8080"
    healthcheck:
      test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:8080/health || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 20s

这里的健康检查会在容器内部执行:

curl -fsS http://127.0.0.1:8080/health

如果命令返回成功,Docker 会认为本次检查通过。

如果连续检查失败达到指定次数,就会将容器标记为:

unhealthy

4. test 是什么意思?

test 是 healthcheck 最重要的配置。

例如:

test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:8080/health || exit 1"]

表示 Docker 定期执行这一条命令。

如果返回码为:

0

通常表示检查成功。

非 0 返回码则表示失败。

因此 healthcheck 实际上就是:

Docker 定期在容器内部运行一个测试命令,并根据退出状态判断应用是否健康。

5. CMD 和 CMD-SHELL 有什么区别?

常见的写法之一是:

test: ["CMD", "curl", "-f", "http://127.0.0.1:8080/health"]

这种方式直接执行命令。

另一种是:

test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:8080/health || exit 1"]

CMD-SHELL 会通过 Shell 执行,因此可以使用:

||

&&

管道;

变量;

其他 Shell 语法。

对于需要稍微复杂一点判断的健康检查,CMD-SHELL 通常更加方便。

6. interval 是什么意思?

例如:

interval: 30s

表示 Docker 大约每隔 30 秒执行一次健康检查。

如果设置太短,例如:

1s

可能会造成没有必要的额外请求和资源消耗。

普通 Web 应用可以根据实际情况使用:

10s

30s

60s

等。

没有必要所有项目都使用相同数值。

7. timeout 是什么意思?

例如:

timeout: 5s

表示单次健康检查允许执行的最长时间。

如果应用在规定时间内没有完成检查,Docker 会将本次检查视为失败。

例如某个接口正常情况下:

100ms

就能够响应,那么 5s 已经比较宽松。

如果后端本身需要很长时间才能返回,则应该根据业务实际情况调整。

不要单纯为了让健康检查变成 healthy,就把 timeout 设置得特别长。

8. retries 是什么意思?

例如:

retries: 3

表示健康检查连续失败达到一定次数以后,Docker 才会将容器标记为:

unhealthy

这样可以避免因为:

瞬时网络波动;

数据库短暂繁忙;

应用偶发超时;

导致容器立刻进入 unhealthy。

如果应用本身对短暂失败比较敏感,可以根据实际情况调整次数。

9. start_period 有什么作用?

很多应用刚启动时需要一些初始化时间。

例如:

数据库加载;

缓存初始化;

Java 应用启动;

数据库迁移;

依赖服务连接。

如果容器刚启动几秒钟就开始严格进行健康检查,很容易出现:

应用还没准备好,Docker 就认为健康检查失败。

可以使用:

start_period: 20s

为应用提供一段启动缓冲时间。

对于启动速度较慢的应用,这个配置非常有用。

10. 为什么配置 healthcheck 后一直 unhealthy?

Docker查看容器healthcheck失败日志

首先执行:

docker ps

确认状态。

然后查看 Health 信息:

docker inspect 容器名称

如果希望快速查看,可以执行:

docker inspect --format '{{json .State.Health}}' 容器名称

例如可能看到:

"Status":"unhealthy"

以及:

"FailingStreak":4

这说明健康检查已经连续失败。

接下来应该继续查看每次 Healthcheck 的具体输出。

11. 查看 healthcheck 失败日志

可以执行:

docker inspect -f '{{range .State.Health.Log}}{{println .Output}}{{end}}' 容器名称

例如可能看到:

curl: (7) Failed to connect to 127.0.0.1 port 8080

说明健康检查命令无法访问本地 8080 服务。

此时应该继续检查:

程序是否启动;

端口是否正确;

应用是否只监听其他地址;

健康检查 URL 是否正确。

不要一看到 unhealthy 就直接重新创建容器。

12. healthcheck 命令必须存在于容器中

这是很容易踩坑的一点。

例如 healthcheck 配置:

test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:8080/health || exit 1"]

前提是:

容器镜像内部存在 curl。

如果镜像非常精简,内部根本没有:

curl

那么健康检查一定失败。

可以进入容器检查:

docker exec -it 容器名称 sh

执行:

which curl

如果没有任何输出,就说明镜像可能没有安装 curl。

这时可以:

使用镜像已有的工具;

制作自己的 Dockerfile 安装需要的工具;

或者调整健康检查方式。

13. 使用 wget 做 HTTP 健康检查

部分 Alpine 或 BusyBox 环境可能包含 wget。

可以根据镜像实际情况使用:

healthcheck:
  test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8080/health >/dev/null 2>&1 || exit 1"]
  interval: 30s
  timeout: 5s
  retries: 3

但同样应该先确认:

which wget

该工具确实存在于容器内部。

不要复制健康检查配置以后才发现容器里根本没有对应命令。

14. TCP 服务怎么做健康检查?

并不是所有服务都有 HTTP 接口。

例如某些数据库、缓存或者 TCP 服务,可以使用端口检查。

如果容器内部存在 nc,可以根据实际情况使用:

healthcheck:
  test: ["CMD-SHELL", "nc -z 127.0.0.1 3306 || exit 1"]
  interval: 30s
  timeout: 5s
  retries: 3

这里仅仅检测:

3306

端口能否建立连接。

但需要注意:

端口能连接,并不一定代表数据库业务逻辑完全正常。

对于 MySQL、PostgreSQL、Redis 等服务,如果镜像提供官方客户端命令,通常可以使用更准确的应用级健康检查。

15. MySQL 健康检查示例

例如 MySQL 可以根据项目实际配置使用:

services:
  mysql:
    image: mysql:8
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
    healthcheck:
      test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -uroot -p$$MYSQL_ROOT_PASSWORD --silent"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

需要注意:

Compose 中:

$$

和:

$

的处理方式不同。

同时不要把真实数据库密码直接写进公开文章或代码仓库。

正式项目应该结合 .env 或其他凭据管理方案使用。

16. healthy 会自动重启 unhealthy 容器吗?

不会因为 healthcheck 变成:

unhealthy

就必然自动重启容器。

healthcheck 的主要作用是:

提供容器健康状态。

而:

restart: unless-stopped

主要针对容器主进程退出后的重启策略。

如果容器主进程还在运行,只是 healthcheck 失败,Docker 通常只是把容器标记为:

unhealthy

不会把 healthcheck 当成“主进程退出”自动处理。

因此不要把:

restart

和:

healthcheck

理解成同一个功能。

17. healthcheck 有什么实际作用?

既然 unhealthy 不一定自动重启,那么 healthcheck 有什么用?

主要用途包括:

快速确认应用真实状态;

监控系统读取容器健康状态;

Docker Compose 控制服务依赖;

运维人员快速发现应用异常;

自动化平台根据健康状态进行后续处理。

例如执行:

docker ps

一眼就可以看到:

(healthy)

还是:

(unhealthy)

比单纯看到:

Up 2 hours

更有参考价值。

18. depends_on 和 healthcheck 怎么配合?

假设:

web

需要连接:

mysql

如果只配置:

depends_on:
  - mysql

通常主要表示启动顺序上的依赖关系。

但:

MySQL 容器已经启动,并不代表 MySQL 已经完成初始化,可以接受连接。

可以结合 healthcheck。

例如:

services:
  mysql:
    image: mysql:8
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
    healthcheck:
      test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -uroot -p$$MYSQL_ROOT_PASSWORD --silent"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

  web:
    image: example/web:latest
    depends_on:
      mysql:
        condition: service_healthy

这样 Compose 在处理依赖时,可以等待 MySQL 达到 healthy 状态后再启动 Web 服务。

19. depends_on 能完全解决数据库启动顺序问题吗?

不能把所有可靠性都依赖在 Compose 启动顺序上。

即使 MySQL 启动时处于 healthy:

后续运行中数据库仍然可能重启;

网络可能短暂中断;

数据库可能出现异常;

连接可能超时。

因此真正可靠的 Web 应用本身也应该具备:

连接失败重试;

合理超时;

断线重连;

错误处理。

depends_on + service_healthy

更适合改善初次启动时的依赖顺序,而不是替代应用自身的容错机制。

20. Dockerfile 自带 HEALTHCHECK 怎么办?

部分 Docker 镜像本身可能已经包含:

HEALTHCHECK

可以执行:

docker inspect 容器名称

查看:

Healthcheck

相关配置。

Docker Compose 中重新定义:

healthcheck:

时,可以根据项目需要覆盖镜像默认健康检查。

但正式修改之前建议先了解镜像原本为什么设计该 Healthcheck。

不要看到默认 unhealthy 就直接把健康检查关闭。

21. 如何临时关闭镜像自带 healthcheck?

如果确实明确不需要镜像默认 Healthcheck,可以在 Compose 中根据实际情况禁用。

例如:

healthcheck:
  disable: true

但这种方式应该谨慎使用。

如果默认健康检查一直失败,更应该先确认:

应用是否真正正常;

检查命令是否适用于当前环境;

配置是否发生变化。

关闭 healthcheck 只会让:

unhealthy

不再显示,并不会自动修复应用本身。

22. healthcheck 接口应该检查什么?

一个好的健康检查接口应该:

响应快;

依赖少;

能够真实反映应用是否可以提供基本服务;

不会执行大量计算;

不会修改业务数据。

例如:

/health

或者:

/healthz

通常只需要返回:

200 OK

不建议 healthcheck 每 10 秒执行一次:

复杂数据库统计;

大文件操作;

第三方 API 请求;

耗时业务流程。

否则健康检查本身也可能给应用增加压力。

23. 健康检查应该检查数据库吗?

取决于业务。

如果 Web 应用没有数据库就完全无法提供服务,那么 Health API 可以适度检查数据库连接。

但如果把大量外部依赖全部加入健康检查:

Redis;

MySQL;

第三方支付;

外部 API;

对象存储;

只要任何一个服务暂时波动,整个容器就可能被标记 unhealthy。

因此应该根据实际业务区分:

应用进程是否存活;

应用是否基本可服务;

关键依赖是否可用。

不要让 Healthcheck 变得过于复杂。

24. 修改 healthcheck 后为什么没变化?

修改:

compose.yaml

以后,需要让 Docker 使用新的容器配置。

可以先验证:

docker compose config

确认 Healthcheck 配置已经被正确解析。

然后执行:

docker compose up -d

如果需要确保重新创建:

docker compose up -d --force-recreate

再查看:

docker ps

刚创建的容器可能先显示:

health: starting

等待一段时间以后才会变成:

healthy

或者:

unhealthy

这是正常过程。

25. 如何查看最终 healthcheck 配置?

执行:

docker inspect -f '{{json .Config.Healthcheck}}' 容器名称

可以看到当前容器实际使用的 Healthcheck 配置。

这样可以确认:

Test

Interval

Timeout

Retries

StartPeriod

是否符合预期。

如果 Compose 文件明明已经修改,但 inspect 还是旧配置,通常说明容器没有按照新配置重新创建。

26. 容器 unhealthy 但网站可以打开怎么办?

这种情况通常说明:

Healthcheck 本身写错了。

例如:

网站实际监听:

8080

但 Healthcheck 检查:

80

或者:

实际接口:

/health

却检查:

/healthz

也可能是:

容器中没有 curl;

DNS 名称错误;

接口需要认证;

检查地址绑定错误。

可以先进入容器,手工运行和 healthcheck 完全相同的命令。

例如:

docker exec -it web sh

然后:

curl -fsS http://127.0.0.1:8080/health

这样最容易发现检查命令本身的问题。

27. 容器 healthy 但外部还是打不开怎么办?

healthy

通常只说明:

容器内部的健康检查通过。

并不代表公网一定可以访问。

如果:

容器 healthy;

服务器本机访问正常;

公网打不开;

则应该继续检查:

Docker 端口映射;

服务器防火墙;

安全组;

Nginx 反向代理;

公网网络。

例如:

docker ps

确认有没有:

0.0.0.0:8080->8080/tcp

如果没有宿主机端口映射,外部可能无法直接访问。

28. Docker Compose 健康检查快速排查顺序

遇到 unhealthy 时,可以按照下面的顺序处理。

第一步:查看状态

docker ps

第二步:查看 Health 信息

docker inspect --format '{{json .State.Health}}' 容器名称

第三步:查看 Health 日志

docker inspect -f '{{range .State.Health.Log}}{{println .Output}}{{end}}' 容器名称

第四步:查看应用日志

docker logs --tail 100 容器名称

第五步:进入容器手工执行健康检查命令

docker exec -it 容器名称 sh

第六步:检查 Compose

docker compose config

第七步:修改以后重新创建

docker compose up -d --force-recreate

按照这个顺序,通常可以判断是:

Healthcheck 配置错误;

检查工具缺失;

应用没有启动;

接口错误;

依赖服务异常。

29. Docker 项目部署建议

如果一台服务器运行多个 Docker Compose 项目,Healthcheck 可以帮助快速了解不同容器的实际运行状态。

如果还没有安装 Docker,可以参考:

安装教程: 服务器上安装docker和docker-compose教程

如果项目越来越多,希望通过 Web 页面统一管理 Compose Stack,可以参考:

相关阅读: 使用 Docker 搭建 Dockge:可视化管理 Docker Compose 项目

如果需要部署 Docker 网站、数据库、监控或其他自托管项目,也可以根据实际业务配置选择莱卡云 Linux 云服务器。

查看官网购买链接: https://www.lcayun.com

30. 总结

Docker 容器显示:

Up

只说明容器主进程仍然运行,并不能完全说明应用真正可用。

通过 Docker Compose 配置:

healthcheck:

可以定期检查应用状态。

最常用的配置包括:

test
interval
timeout
retries
start_period

出现:

unhealthy

以后,应该优先查看:

docker inspect --format '{{json .State.Health}}' 容器名称

再结合:

docker logs --tail 100 容器名称

判断问题。

如果存在数据库等启动依赖,还可以配合:

depends_on:
  mysql:
    condition: service_healthy

改善 Compose 项目启动顺序。

需要特别注意:

unhealthy 本身并不等于 Docker 会自动重启容器。

Healthcheck 的核心作用是帮助 Docker、Compose 和运维人员判断:

容器中的应用是否真正处于健康状态。

赞(0)
未经允许不得转载:莱卡云 » Docker Compose healthcheck 怎么配置?容器健康检查教程