从里面停止码头工人的容器

时间:2015-07-21 11:52:45

标签: docker

我在docker容器中运行了一个cronjob,它检查所有服务是否按预期运行。如果这个cronjob确定存在问题我想停止docker容器(从内部......)

不幸的是exit只是停止了我的cronjob脚本

7 个答案:

答案 0 :(得分:7)

基本上,您需要PID 1才能退出以停止容器。

我最初认为kill -s SIGKILL 1会起作用,但PID 1受到保护,所以它没有。

正如@Thomasleveil所建议的那样,您可以将trap "exit" SIGINT SIGTERM等代码添加到PID 1脚本中,这意味着当发送kill -s SIGINT 1时,该过程将退出。我稍微倾向于使用这个方法(直接杀死子进程),因为它为父进程提供了清理机会,并且父进程应该能够在没有awk的情况下找到子进程的PID。 / p>

但是,如果你正在运行多个进程,你应该考虑使用supervisord或runit之类的东西。

答案 1 :(得分:2)

我遇到了同样的问题,并使用docker的healthcheck功能解决了这个问题。

您可以在heahthcheck.sh之类的文件中添加检查以验证服务。然后在您的Dockerfile后面加上以下内容:

# Healthcheck
COPY healthcheck.sh /
RUN chmod +x /healthcheck.sh

HEALTHCHECK --interval=10s --retries=5 CMD /healthcheck.sh

这可确保docker通过在指定间隔内运行脚本来检查容器的运行状况,并且如果该脚本连续5次失败,则将状态标记为不正常。

现在,要在状态不正常的情况下重新启动容器,可以像这样使用autoheal

docker run -d \
    --name autoheal \
    --restart=always \
    -e AUTOHEAL_CONTAINER_LABEL=all \
    -v /var/run/docker.sock:/var/run/docker.sock \
    willfarrell/autoheal

这将在每次容器状态不正常时重新启动容器。

答案 2 :(得分:0)

我最近不得不弄清楚这一点。经过无奈之后,我的想法是这样的:

在您的dockerfile中,指定一个ENTRYPOINT:

ENTRYPOINT ["/entrypoint.sh"]

然后,提供这样的脚本。除了调用您的应用程序外,它不需要执行任何其他操作。随时向脚本添加其他设置,但是请注意,如果脚本在调用您的应用程序后执行任何操作,则可能会掩盖您应用程序的返回代码。如果与您相关,请确保脚本捕获返回码并将其作为自己的返回码传播出去。

注意:请勿使用exec来调用您的应用程序!

结果将是PID 1属于entrypoint.sh,而您的应用程序将具有其他一些PID。矿山倾向于降落在PID 9或10上。

然后,当您需要终止应用程序时,只需确定其PID并调用kill -SIGKILL $PIDpkill -SIGKILL yourapp。您的过程不是PID 1,将接收到该信号并立即退出。您的entrypoint.sh将立即退出,因为这是您设计退出流程后要执行的操作。

答案 3 :(得分:0)

受@JakeRobb启发: 您可以使用以下命令执行Docker:

/bin/bash -c "while true; do sleep infinity || exit 0; done"

这将对低于1的PID执行睡眠。一旦杀死它,循环将退出。为此,在docker内部使用:

pkill -f sleep

答案 4 :(得分:0)

我的自杀示例/usr/local/bin/docker-entrypoint.sh

#!/bin/sh
#

# Following guard prevents to stuck containers in DIND GitLab Runner
# If container still works in 300 seconds, this will kill yourself
THE_PID=$$
if [ $THE_PID -eq 1 ]; then
    # Docker does not allow kill process 1, so restart as child process
    /usr/local/bin/docker-entrypoint.sh
    exit $?
fi
(sleep 300; echo "Killing process: $THE_PID"; kill -9 $THE_PID) &


YOUR_SCRIPT_TEXT....

答案 5 :(得分:-1)

我杀死了“阻塞进程”,即您的docker正在运行的主要进程;就像这样(我在这种情况下,docker正在运行sleep infinity命令以进行演示)。

ps -afx | grep sleep | awk'{print $ 1}'| xargs杀死-9

答案 6 :(得分:-3)

我试图杀死进程1但没有成功。

使用shutdown -h now尝试@ zero323的评论。它工作正常(对不起,我不能直接投票,因为它不在答案列表中)。