使用 .sh 脚本进行 docker healthchecks

Loa*_*ing 9 bash docker

现在在这个问题上坐了大约两个小时,我快疯了

这是 bash 脚本示例:

#!/bin/bash

exit 0;
Run Code Online (Sandbox Code Playgroud)

这是泊坞窗文件:

HEALTHCHECK --interval=2s CMD HealthCheckTest.sh || exit 1
Run Code Online (Sandbox Code Playgroud)

我仍然总是不健康。

我想要做的是在我的 bash 脚本中添加一些逻辑来确定容器是否健康。

git*_*ver 6

4 年内有 7,000 次浏览,但没有一个被接受的答案,我认为这对于那些学习者来说仍然是一个有效的问题。

TL;DR该脚本可能不在容器的 shell 中$PATH,因此 Docker 的 HEALTHCHECK 在不传递完整或相对路径的情况下无法找到它。

这是原始问题的示例,重新创建失败(没有|| exit 1操作员屏蔽出口):

Dockerfile:

FROM nginx

ADD --chmod=777 HealthCheckTest.sh .

HEALTHCHECK --interval=2s CMD HealthCheckTest.sh
Run Code Online (Sandbox Code Playgroud)

健康检查测试.sh

FROM nginx

ADD --chmod=777 HealthCheckTest.sh .

HEALTHCHECK --interval=2s CMD HealthCheckTest.sh
Run Code Online (Sandbox Code Playgroud)

然后构建它docker build --tag nginx-healthcheck-broken .

容器将运行 ( docker run nginx-healthcheck-broken),但如果您docker ps在另一个终端中键入,您会在状态下看到它(unhealthy)。您可以通过使用并查找运行状况来检查失败的原因docker inspect <container sha>,它可能如下所示:

#!/bin/bash

exit 0;
Run Code Online (Sandbox Code Playgroud)

修复方法是添加执行它的路径,在本示例中,文件位于当前工作目录中,因此您可以使用./.

Dockerfile:

FROM nginx

ADD --chmod=777 HealthCheckTest.sh .

HEALTHCHECK --interval=2s CMD ./HealthCheckTest.sh
Run Code Online (Sandbox Code Playgroud)

现在重建:docker build --tag nginx-healthcheck-fixed .

Docker 现在应该显示容器的 HEALTHCHECK 状态是健康的,在docker ps和中docker inspect <container sha>

            "Health": {
                "Status": "unhealthy",
                "FailingStreak": 54,
                "Log": [
                    {
                        "Start": "2023-04-14T15:26:44.650809765-07:00",
                        "End": "2023-04-14T15:26:44.70105688-07:00",
                        "ExitCode": 1,
                        "Output": "/bin/sh: 1: HealthCheckTest.sh: not found\n"
                    },
Run Code Online (Sandbox Code Playgroud)

PS 原因|| exit 1来自于Dockerfile 参考文档

Docker 期望 HEALTHCHECK 退出代码为 0(成功)或 1(不健康),而 2 显然是保留供将来使用。在大多数 shell 中,||运算符是 OR 语句,类似于 if 语句,特别是如果上一个命令失败(任何非零退出),则运行下一个命令。添加|| exit 1将屏蔽之前的失败,并确保失败的退出代码始终为 1。

如果您认为 HEALTHCHECK 的命令可能不仅仅是一个脚本,例如,curl如果域不存在,则以 6 退出,这更有意义。缺点是它掩盖了原始的退出代码。


pam*_*mit -3

如果您使用 Docker Compose,还可以使用 Compose 健康检查:

https://docs.docker.com/compose/compose-file/compose-file-v2/#healthcheck

您还可以在 bash 脚本中定义健康检查,可以使用ENTRYPOINTin调用该脚本Dockerfile,例如:

https://github.com/ledermann/docker-rails/blob/develop/docker/wait-for-services.sh