当 docker 以 PID 1 运行时,为什么我不能在 docker 中按 CTRL-C 使其睡眠无穷大

问题描述 投票:0回答:2

案例:我们有一个运行 bash 脚本的 docker 容器,需要永远“阻止”(因为它公开了另一个容器的卷,但有时我们需要这样做还有其他原因)。

我认为这可行:

exec sleep infinity;

ps aux 然后给出“sleep”作为 PID 1。太好了,我想,然后它会接收我们从容器外部发送的信号。例如:

docker kill -s INT container_name

但这不起作用,容器继续运行(也适用于 SIGTERM)。正常的杀戮确实有效,但我不明白为什么会有差异(这让我非常恼火):

docker kill container_name

当“sleep”在我的容器中以 PID 1 运行时,为什么我无法使用 SIGINT/SIGTERM 终止它?我相信当其他东西(如 bash 脚本)在容器中以 PID 1 运行时,我可以使用 SIGINT/SIGTERM 杀死它们。

bash docker sleep sigint sigkill
2个回答
6
投票

这有什么用吗? https://www.fpcomplete.com/blog/2016/10/docker-demons-pid1-orphans-zombies-signals

问题基本上出在进程号 1 上。Linux/unix 内核不愿意以常规方式向该进程发出信号,因为它应该是 init。如果 init 进程终止,系统会立即发出恐慌并重新启动。如果您的进程 1 没有信号处理程序,则该信号就会被丢弃。 Sleep 没有任何信号的处理程序,但您可以构建一个 bash 脚本。

基本上,您需要做的是在 dockerfile 中使用 exec 形式,并将 sleep Infinity 分成循环,因为 shell 执行命令时不会触发 bash 陷阱。这会向正在运行的进程 1 发送信号并捕获它:

Dockerfile:

FROM ubuntu
ADD foo.sh /tmp
RUN ["/tmp/foo.sh"]

foo.sh:

#!/bin/bash

trap "echo signal;exit 0" SIGINT 

while :
do
    sleep 1
done

这将对 docker Kill --signal=SIGINT 做出反应。


0
投票

使用此脚本作为初始化进程:

trap "echo Shutting down; exit 0" SIGTERM SIGINT SIGKILL
/bin/sleep infinity &
wait

例如:与

ENTERYPOINT ["/bin/bash", "-c", "trap \"echo Shutting down; exit 0\" SIGTERM SIGINT SIGKILL; /bin/sleep infinity & wait"]

© www.soinside.com 2019 - 2024. All rights reserved.