如何停止运行睡眠的 docker 容器?

gio*_*oni 5 docker

sleep 当然,它是大多数复杂过程的替代品。

这个 Dockerfile(如您所见,使用 exec 形式,因此只有一个进程在运行,并且没有 的子进程bash):

FROM busybox
CMD ["/bin/sleep", "100000"]
Run Code Online (Sandbox Code Playgroud)

创建一个不间断的容器:

docker build -t kill-sleep .
docker run --rm --name kill-sleep kill-sleep
Run Code Online (Sandbox Code Playgroud)

当我试图阻止它时:

time docker stop kill-sleep

kill-sleep
real    0m10.449s
user    0m0.021s
sys     0m0.027s
Run Code Online (Sandbox Code Playgroud)

命令在容器被杀死前 10 秒超时。

问题不在于sleep不处理信号,因为如果我在主机上运行它:

sleep 100000
# in another shell
ps faxww | grep sleep
kill -TERM 31333  # the PID
Run Code Online (Sandbox Code Playgroud)

该过程立即停止。

问题可能与它在容器中作为 PID 1 运行的事实有关,但我还没有看到相关的参考文档。

Att*_*tie 7

当你运行时docker stop ...会发生一些事情

  1. docker将 a 发送SIGTERM到容器的主进程。该进程能够屏蔽/忽略 a SIGTERM,如果它这样做(或在不终止的情况下处理它)“什么都不会发生”。
  2. 超时后(默认 10 秒),dockerSIGKILL主进程发送一个。该信号不能被进程屏蔽,因此它立即死亡,没有机会执行关闭程序。

理想情况下,在其中运行的进程dockerSIGTERM及时响应,在终止之前处理所有内务。

如果您知道该进程要么没有任何内务要执行(例如:)sleep,要么不会正确响应SIGTERM,您可以使用-t标志指定更短(或更长)的超时:

-t, --time=10
    Seconds to wait for stop before killing it
Run Code Online (Sandbox Code Playgroud)

例如,在您的情况下,您可能希望运行docker stop -t 0 ${CONTAINER}.


此信号行为不同的原因是由于在sleepPID = 1 下运行。

通常(例如:以 PID != 1 运行),进程未明确处理的任何信号都会导致进程终止 - 尝试发送sleepa SIGUSR1

但是,当以 PID = 1 运行时,未处理的信号将被忽略,否则最终会出现内核恐慌:

Kernel panic - not syncing: Attempted to kill init!
Run Code Online (Sandbox Code Playgroud)

您可以使用 docker 工具向 docker 容器发送信号,例如:

docker kill -s TERM kill-sleep
Run Code Online (Sandbox Code Playgroud)

正如我们所看到的,这没有达到预期的效果,而这样做:

docker kill -s KILL kill-sleep
Run Code Online (Sandbox Code Playgroud)

一个实验

文件

-t, --time=10
    Seconds to wait for stop before killing it
Run Code Online (Sandbox Code Playgroud)

运行文件

Kernel panic - not syncing: Attempted to kill init!
Run Code Online (Sandbox Code Playgroud)

现在,运行

docker kill -s TERM kill-sleep
Run Code Online (Sandbox Code Playgroud)

这在另一个终端中:

docker kill -s KILL kill-sleep
Run Code Online (Sandbox Code Playgroud)

我们观察到相同的 10 秒延迟/超时。

一个办法

现在让我们处理SIGTERM. Backgrounding和wait荷兰国际集团为sleep是由于POSIX外壳手柄信号是如何(见为更多)。

运行文件

FROM busybox
COPY run.sh /run.sh
RUN chmod +x /run.sh
CMD "/run.sh"
Run Code Online (Sandbox Code Playgroud)

再次运行命令,我们就会看到我们所追求的!

#!/bin/sh

echo "sleeping"
sleep 100000
Run Code Online (Sandbox Code Playgroud)