基于healthcheck重新启动不健康的docker容器

Gov*_*las 38 health-monitoring docker

我正在使用Docker version 17.09.0-ce我看到容器被标记为不健康的健康检查失败.

是否有选项可以重新启动容器而不是将容器保持为不健康状态.

Nav*_*cky 54

重新启动unhealty容器功能在原始PR(https://github.com/moby/moby/pull/22719)中,但在讨论后被删除,并认为稍后将作为RestartPolicy的增强功能完成.

此时,您可以使用此变通方法自动重新启动unhealty容器:https://hub.docker.com/r/willfarrell/autoheal/

这是一个示例撰写文件:

version: '2'
services:
  autoheal:
    restart: always
    image: willfarrell/autoheal
    environment:
      - AUTOHEAL_CONTAINER_LABEL=all
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
Run Code Online (Sandbox Code Playgroud)

只需执行docker-compose up -d此操作即可

  • 这带来了巨大的安全风险 https://news.ycombinator.com/item?id=17983623 (6认同)
  • @InsOp 那么你有什么建议?如何在不授予容器访问 Docker 的权限的情况下完成此操作? (3认同)

小智 16

不健康的 docker 容器可以通过简单的 crontab 规则重新启动:

* * * * * docker ps -f health=unhealthy --format "docker restart {{.ID}}" | sh
Run Code Online (Sandbox Code Playgroud)

  • 可能更安全的做法是 `docker ps -q -f health=unhealthy | xargs docker restart`而不是调用 shell。 (7认同)

Nar*_*sim 15

您可以通过设置智能 HEALTHCHECK 和适当的重启策略来自动重启不健康的容器。

Docker 重启策略应该是always或 之一unless-stopped

HEALTHCHECK 应该实现一个逻辑,当它不健康时杀死容器。

在下面的例子中,我使用curl了它的内部重试机制并将它(在失败/服务不健康的情况下)通过管道传递给kill命令。

HEALTHCHECK --interval=5m --timeout=2m --start-period=45s \
   CMD curl -f --retry 6 --max-time 5 --retry-delay 10 --retry-max-time 60 "http://localhost:8080/health" || bash -c 'kill -s 15 -1 && (sleep 10; kill -s 9 -1)'
Run Code Online (Sandbox Code Playgroud)

这里要理解的重要一步是重试逻辑是自包含在curl命令中的,这里的Docker重试实际上是强制性的但没用。然后如果curlHTTP 请求失败 3 次,则kill执行。首先它向容器中的所有进程发送一个 SIGTERM,以允许它们正常停止,然后在 10 秒后发送一个 SIGKILL 以完全终止容器中的所有进程。必须注意的是,当容器的 PID1 死亡时,容器本身也会死亡并调用重启策略。

陷阱:kill在 bash 中的行为与在 sh 中的行为不同。在 bash 中,您可以使用-1信号通知所有 PID 大于 1 的进程死亡。

  • 是的,它进入了无限循环。停止它的唯一方法是通过“docker compose stop”或“docker compose rm -f”。有一个超级复杂的替代方案可以解决此问题。即:将 Docker 套接字挂载到容器内,在容器内的“.sh”文件中实现重试逻辑,在卷上写入计数器以使其持久化,当计数器大于尝试次数时,使用 docker套接字向容器本身发送“停止”消息。:) (2认同)

小智 8

对于独立容器,Docker 没有本地集成来在健康检查失败时重新启动容器,尽管我们可以使用 Docker 事件和脚本实现相同的功能。健康检查更好地与 Swarm 集成。通过将健康检查集成到 Swarm 中,当服务中的容器不健康时,Swarm 会自动关闭不健康的容器并启动一个新容器,以保持服务副本计数中指定的容器计数。


Wha*_*hat 8

您可以尝试在您的 Dockerfile 中添加如下内容:

HEALTHCHECK --interval=5s --timeout=2s CMD curl --fail http://localhost || kill 1
Run Code Online (Sandbox Code Playgroud)

不要忘记--restart always选项。

kill 1将终止容器中 pid 为 1 的进程并强制容器退出。通常由 CMD 或 ENTRYPOINT 启动的进程的 pid 为 1。

不幸的是,此方法可能不会将容器的状态更改为不健康,因此请小心使用。

  • 这不是在第一次失败的卷曲时杀死容器吗? (2认同)

小智 6

根据https://codeblog.dotsandbrackets.com/docker-health-check/

创建容器并添加“restart:always”。

在使用healthcheck时,需要注意以下几点:

对于独立容器,Docker 没有本机集成来在运行状况检查失败时重新启动容器,尽管我们可以使用 Docker 事件和脚本来实现相同的目的。健康检查与Swarm更好地集成。通过将健康检查集成到 Swarm 中,当服务中的容器不健康时,Swarm 会自动关闭不健康的容器并启动新容器以维持服务副本计数中指定的容器计数。

  • 请将您的所有答案放在回复中而不是链接中。 (3认同)

小智 5

Docker 有多种方法来获取有关容器运行状况的详细信息。您可以配置运行状况检查及其运行频率。此外,可以对容器内运行的应用程序运行运行状况检查,例如 http(这将使用curl --fail选项)。您可以查看health_status事件以获取详细信息。

有关不健康容器的详细信息,inspect 命令会派上用场docker inspect --format='{{json .State.Health}}' container-name (有关更多详细信息,请参阅https://blog.newrelic.com/2016/08/24/docker-health-check-instruction/。)

您应该首先解决导致“不健康”标签的错误情况(每当运行状况检查命令运行并获取退出代码 1 时)。这可能需要也可能不需要 Docker 重新启动容器,具体取决于错误。如果您自动启动/重新启动容器,则捕获启动错误或记录它们以及运行状况检查状态可以帮助快速解决错误。如果您对自动启动感兴趣,请检查链接。