当它以 PID 1 运行时,为什么我不能 CTRL-C 在 docker 中睡眠无限

Why can't I CTRL-C a sleep infinity in docker when it runs as PID 1

案例:我们有一个 docker 容器,它 运行 是一个 bash 需要永远 "block" 的脚本(因为它为另一个容器公开了一个卷,但是是我们有时需要这个的其他原因)。

当时我认为这可行:

exec sleep infinity;

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

docker kill -s INT container_name

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

docker kill container_name

当 运行 在我的容器中作为 PID 1 时,为什么我不能用 SIGINT/SIGTERM 杀死 "sleep"?我相信我可以用 SIGINT/SIGTERM 杀死其他东西(比如 bash 脚本),当它们 运行 作为容器中的 PID 1 时。

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

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

基本上你需要做的是在你的 docker 文件中使用 exec 形式,并将你的无限睡眠分成一个循环,因为 bash 陷阱不会被触发而 shell执行命令。这向 运行 进程 1 发送信号并捕获它:

Docker 文件:

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 作出反应。