Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/docker/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/apache-flex/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从内部停止docker容器_Docker - Fatal编程技术网

从内部停止docker容器

从内部停止docker容器,docker,Docker,我在docker容器中运行了一个cronjob,它检查是否所有服务都按预期运行。如果此cronjob确定存在问题,我希望停止docker容器(从内部…) 不幸的是,退出只是停止了我的cronjob脚本基本上,您需要PID 1退出才能停止容器 我最初认为kill-s SIGKILL 1可以工作,但PID 1是受保护的,所以它不能工作 正如@thomaslevel所建议的,您可以向PID 1脚本添加代码,例如trap“exit”SIGINT SIGTERM,这意味着当发送kill-s SIGINT

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


不幸的是,
退出
只是停止了我的cronjob脚本

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

我最初认为
kill-s SIGKILL 1
可以工作,但PID 1是受保护的,所以它不能工作

正如@thomaslevel所建议的,您可以向PID 1脚本添加代码,例如
trap“exit”SIGINT SIGTERM
,这意味着当发送
kill-s SIGINT 1
时,进程将退出。与您提出的方法(直接杀死子进程)相比,我更喜欢这种方法,因为它给了父进程一个清理的机会,并且父进程应该能够在没有awk的情况下找到子进程的PID


处理这个问题最简单的方法是使用某种监管流程,Docker现在提供了一个名为“tini”的流程。只需运行将参数
--init
添加到
docker run
中,docker就会在容器中将tini设置为PID 1。完整描述如下:

我试图终止进程1,但没有成功

shutdown-h now
尝试@zero323的注释。它工作正常(抱歉,我不能直接投票支持它,因为它不在答案列表中)。

我杀死了“阻塞进程”,即docker正在运行的主进程;像这样(我认为docker正在运行sleep infinity命令进行演示)


ps-afx | grep sleep | awk{print$1}| xargs kill-9

我最近不得不弄清楚这一点。在经历了许多挫折之后,我发现:

在dockerfile中,指定入口点:

ENTRYPOINT ["/entrypoint.sh"]
然后,提供这样一个脚本。它不需要做任何事情,只需要调用您的应用程序。可以随意向脚本添加其他设置,但请注意,如果脚本在调用应用程序后执行任何操作,它可能会屏蔽应用程序的返回代码。如果这与您相关,请确保脚本捕获返回代码并将其作为自己的返回代码传播出去

注意:不要使用
exec
调用应用程序

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

然后,当您需要终止应用程序时,只需确定其PID并调用
kill-SIGKILL$PID
,或
pkill-SIGKILL-yourapp
。您的进程(不是PID 1)将收到信号并立即退出。您的
entrypoint.sh
将立即退出,因为这是您在流程退出后设计它的目的。

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

/bin/bash -c "while true; do sleep infinity || exit 0; done"
这将在低于1的PID上执行睡眠。一旦你杀死它,循环就会退出。为此,从docker内部使用:

pkill -f sleep

我也遇到了同样的问题,我用docker的特性解决了这个问题

您可以在类似
heahtchcheck.sh
的文件中添加检查以验证您的服务。然后在
Dockerfile
中添加如下内容:

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

HEALTHCHECK --interval=10s --retries=5 CMD /healthcheck.sh
这确保docker通过在指定的时间间隔内运行脚本来检查容器的运行状况,如果脚本连续失败5次,则会将状态标记为“不健康”

现在,为了在状态不正常时重新启动容器,您可以使用以下方法:

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

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

我的self-kill/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....

你的容器是基于什么图像的?它来自ubuntu:12.04这看起来像是一张图片。您可能希望使用流程管理器作为入口点来管理多个流程,并使用事件侦听器在特定条件下终止supervisord。我也想到了这一点,但无法使其工作。你想要一个用于展示的Dockerfile吗?将
trap“exit”SIGINT SIGTERM
添加到我的shell脚本允许我在PID
1
上使用
kill
命令。我想我们无法解释OP的具体情况,除非我们知道使用了什么docker图像,实际上对我有效的只是扼杀了每一个进程。我有一个作为PID 1运行的shell脚本,它有一个长时间运行的子进程。子进程不受保护,仅杀死该子进程即可让我退出计算机。ps x|awk{{print$1}}awk'NR>1'| xargskill@NilsZiehn你应该详细回答自己的问题,这将有助于其他人了解实际问题以及克服问题的不同方法。另外,请看一下
pkill
命令,如果有人到了这里,一种直接正确的方法是使用tini for init,它内置于docker中。查看:这是最新ubuntu图片中发生的事情:>root@b968bf313300:/#shutdown-h现在无法连接到总线:没有这样的文件或目录无法与init守护进程通信。它什么也没做,因为这不起作用而被否决<代码>关闭与
initd
/
systemd
/etc通信,在非容器场景中,这是PID 1。在容器中,它不存在。对于我来说,使用node:10映像,我得到
bash:shutdown:command not found
这对于杀死入口点非常有效,但是不允许杀死可能在没有入口点的情况下运行的容器。当然,但是你可以为任何容器创建自己的Dockerfile。以原始Dockerfile为基础(如果有),编写并复制相应的entrypoint.sh,然后包含相应的entrypoint。这对已经运行的容器没有帮助,因此,
docker会杀死来自外部的容器,并用更新的图像替换它们。@JakeRobb,谢谢你的想法。我已经发布了一个受此启发的答案