我正在使用 Docker版本17.09.0-ce
,并且我看到容器被标记为不健康。有没有选项可以让容器重新启动而不是保持不健康的状态?
我正在使用 Docker版本17.09.0-ce
,并且我看到容器被标记为不健康。有没有选项可以让容器重新启动而不是保持不健康的状态?
在最初的 PR 中(https://github.com/moby/moby/pull/22719),“重新启动不健康容器”功能已存在,但在讨论后被移除,并被认为以后可以作为 RestartPolicy 的增强功能。
目前,您可以使用此解决方法自动重新启动不健康的容器: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
只需在此执行docker-compose up -d
通过设置智能的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)'
重要的一步是理解重试逻辑已经包含在curl
命令中,Docker重试实际上是强制性的但无用的。 如果curl
HTTP请求失败3次,则执行kill
命令。 首先,它向容器中的所有进程发送SIGTERM信号,以允许它们正常停止,然后在10秒后发送SIGKILL信号来完全杀死容器中的所有进程。必须注意,当容器的PID1死亡时,容器本身也会死亡并触发重启策略。
注意:在bash和sh中,kill
行为不同。 在bash中,您可以使用-1
向所有PID大于1的进程发送信号以使其死亡。
kill
文档:https://linux.die.net/man/1/killcurl
文档:https://curl.haxx.se/docs/manpage.htmldocker
重新启动文档:https://docs.docker.com/compose/compose-file/compose-file-v2/#restartdocker compose stop
或 docker compose rm -f
。有一个超级复杂的替代方案来解决这个问题。即:在容器内挂载Docker套接字,在容器内的.sh
文件中实现重试逻辑,在卷上写入计数器以使其持久化,并且当计数器大于尝试次数时,使用Docker套接字向容器本身发送stop
消息。 :) - Naramsimretries
参数与 @naramsim 在评论中解释的目的不同。 - AATHITH RAJENDRAN--retry-connrefused
作为 curl 命令的选项添加进去。否则,如果服务器由于某种原因没有启动,curl 将在第一次尝试时失败。 - robertsLando通过简单的crontab规则,不健康的docker容器可以重新启动:
* * * * * docker ps -f health=unhealthy --format "docker restart {{.ID}}" | sh
docker ps -q -f health=unhealthy | xargs docker restart
而不是调用一个 shell。 - slhck-r
或--no-run-if-empty
标志来运行xargs命令,例如:
docker ps -q -f health=unhealthy | xargs --no-run-if-empty docker restart
。 - undefined对于独立容器而言,Docker并没有原生集成在健康检查失败时重启容器的功能,但我们可以使用Docker事件和脚本实现相同的效果。在Swarm中,健康检查得到更好的集成。将健康检查集成到Swarm中后,当服务中的容器不健康时,Swarm会自动关闭不健康的容器并启动一个新的容器以维护服务的副本数量指定的容器计数。
您可以尝试在Dockerfile中添加类似于以下内容的内容:
HEALTHCHECK --interval=5s --timeout=2s CMD curl --fail http://localhost || kill 1
不要忘记--restart always
选项。
kill 1
将在容器中杀死pid为1的进程并强制退出容器。通常由CMD或ENTRYPOINT启动的进程具有pid 1。
不幸的是,这种方法可能不会将容器的状态更改为不健康,因此请谨慎使用。
curl --fail
选项)。您可以查看health_status
事件以获取详细信息。docker inspect --format='{{json .State.Health}}' container-name
(有关详细信息,请参见https://blog.newrelic.com/2016/08/24/docker-health-check-instruction/)。docker inspect --format="{{json .State.Health}}" name-of-your-container
。 - AbsolutelyFreeWeb
docker events -f event=health_status
(https://docs.docker.com/engine/reference/commandline/events/#extended-description) 来检查容器的健康状况,并根据结果采取相应的措施。 - Tarun Lalwani