当Docker容器的PID1退出时,其他进程会发生什么?

Mic*_*man 15 linux cgroups docker

考虑以下内容,它sleep 60在后台运行然后退出:

$ cat run.sh 
sleep 60&
ps
echo Goodbye!!!
$ docker run --rm -v $(pwd)/run.sh:/run.sh ubuntu:16.04 bash /run.sh
  PID TTY          TIME CMD
    1 ?        00:00:00 bash
    5 ?        00:00:00 sleep
    6 ?        00:00:00 ps
Goodbye!!!
Run Code Online (Sandbox Code Playgroud)

这将启动一个Docker容器,bash作为PID1.然后fork/execs一个sleep进程,然后bash退出.当Docker容器死亡时,该sleep过程也会以某种方式死亡.

我的问题是:该sleep过程被杀死的机制是什么?我试图陷入SIGTERM一个子进程,似乎没有被绊倒.我的假设是,SIGKILL当关闭容器正在使用的cgroup时,某些东西(Docker或Linux内核)正在发送,但我发现没有任何文档可以澄清这一点.

编辑我最接近解释的是baseimage-docker的以下引用:

如果您的init进程是您的应用程序,那么它可能只关闭自己,而不是容器中的所有其他进程.然后,内核将强制终止其他进程,而不是让他们有机会正常关闭,可能导致文件损坏,过时的临时文件等.您真的想要优雅地关闭所有进程.

因此,至少根据这一点,暗示当容器退出时,内核将向所有剩余进程发送SIGKILL.但是我仍然希望明确它如何决定这样做(即,它是cgroups的一个特征吗?),理想情况下,一个更权威的来源会很好.

Mic*_*man 6

好吧,我似乎已经提出了一些更可靠的证据,这实际上是 Linux 内核在执行终止操作。在clone(2)手册页中,有这个有用的部分:

CLONE_NEWPID(自 Linux 2.6.24 起)

在新命名空间中创建的第一个进程(即,使用 CLONE_NEWPID 标志创建的进程)的 PI​​D 为 1,并且是命名空间的“init”进程。命名空间内孤立的孩子将被重新分配给这个进程,而不是 init(8)。与传统的 init 进程不同,PID 命名空间的“init”进程可以终止,如果终止,命名空间中的所有进程都会终止。

不幸的是,这对于命名空间中的进程究竟如何终止仍然含糊不清,但这可能是因为与正常的进程退出不同,进程表中没有留下任何条目。不管是什么情况,似乎很清楚:

  • 内核本身正在杀死其他进程
  • 他们没有以一种允许他们有机会进行清理的方式被杀死,使其(几乎?)与 SIGKILL 相同