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

What happens to other processes when a Docker container's PID1 exits?

考虑以下,它在后台运行 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!!!

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

我的问题是:sleep进程被杀死的机制是什么?我尝试在子进程中捕获 SIGTERM,但似乎没有被触发。我的假设是,当关闭容器正在使用的 cgroup 时,某些东西(Docker 或 Linux 内核)正在发送 SIGKILL,但我在任何地方都找不到任何文档来阐明这一点。

EDIT 我最接近的解释是引用自 baseimage-docker:

If your init process is your app, then it'll probably only shut down itself, not all the other processes in the container. The kernel will then forcefully kill those other processes, not giving them a chance to gracefully shut down, potentially resulting in file corruption, stale temporary files, etc. You really want to shut down all your processes gracefully.

所以至少根据这个,言外之意是当容器退出时,内核会向所有剩余的进程发送一个SIGKILL。但我仍然想清楚它是如何决定这样做的(即,它是 cgroups 的一个特性吗?),理想情况下,一个更权威的来源会很好。

好吧,我似乎找到了一些更确凿的证据,证明这实际上是 Linux 内核在执行终止。在 clone(2) 手册页中,有这个有用的部分:

CLONE_NEWPID (since Linux 2.6.24)

The first process created in a new namespace (i.e., the process created using the CLONE_NEWPID flag) has the PID 1, and is the "init" process for the namespace. Children that are orphaned within the namespace will be reparented to this process rather than init(8). Unlike the traditional init process, the "init" process of a PID namespace can terminate, and if it does, all of the processes in the namespace are terminated.

不幸的是,命名空间中的进程究竟是如何终止的仍然含糊不清,但这可能是因为,与正常的进程退出不同,进程中没有留下任何条目 table。无论如何,很明显:

  • 内核本身正在杀死其他进程
  • 它们不会以让它们有任何机会进行清理的方式被杀死,使其(几乎?)与 SIGKILL 相同