从内部停止Docker容器

d7v8vwbk  于 2023-08-03  发布在  Docker
关注(0)|答案(7)|浏览(127)

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

l7wslrjt

l7wslrjt1#

基本上,您需要PID 1退出以停止容器。
执行kill -s SIGKILL 1将不起作用,因为PID 1受到保护。
正如@Thomasleveil所建议的那样,您可以将trap "exit" SIGINT SIGTERM这样的代码添加到PID 1脚本中,这意味着当发送kill -s SIGINT 1时,进程将退出。比起你提出的方法(直接杀死子进程),我更喜欢这个方法,因为它给了父进程一个清理的机会,而且父进程应该能够在没有awk的情况下找到子进程的PID。
处理这个问题最简单的方法是使用某种监督进程,Docker现在方便地提供了一个名为“tini”的进程。只需运行add参数--init to docker run,Docker就会将tini设置为容器中的PID 1。完整的描述在这里:https://docs.docker.com/engine/reference/run/#specify-an-init-process

nafvub8i

nafvub8i2#

我遇到了同样的问题,我通过使用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


这将在每次容器状态变得不健康时重新启动容器。

2ul0zpep

2ul0zpep3#

我最近不得不弄清楚这一点。在经历了很多挫折之后,我最终想到了这个:
在dockerfile中,指定一个ENTRYPOINT:

ENTRYPOINT ["/entrypoint.sh"]

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

  • 注意:不要使用exec来调用你的应用程序!*

结果将是PID 1属于entrypoint.sh,而您的应用程序将具有其他PID。我的倾向于落在PID 9或10上。
然后,当需要终止应用程序时,只需确定其PID并调用kill -SIGKILL $PIDpkill -SIGKILL yourapp。你的进程,不是PID 1,将收到信号并立即退出。您的entrypoint.sh将立即退出,因为这是您设计的在流程退出后执行的操作。

mlnl4t2r

mlnl4t2r4#

来自@JakeRobb的灵感:你可以使用以下命令执行docker:

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

字符串
这将在低于1的PID上执行休眠。一旦你杀了它,循环就会退出。为此,在docker中用途:

pkill -f sleep

uajslkp6

uajslkp65#

/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....

字符串

owfi6suc

owfi6suc6#

我杀死了“阻塞过程”,即。docker正在运行的主进程;像这样(在这种情况下,docker正在运行一个sleep infinity命令,用于演示目的)。
ps-afx| grep睡眠|awk '{print $1}'| xargs kill-9

qgelzfjb

qgelzfjb7#

我试图杀死进程1,但没有成功。
给予用shutdown -h now评论@zero323。它工作正常(对不起,我不能直接投票给它,因为它不在答案列表中)。

相关问题