考虑以下内容,在后台运行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 / exec一个sleep
过程,然后bash
退出。 当Docker容器死亡时, sleep
过程也会死亡。
我的问题是:什么是sleep
过程被杀死的机制? 我试图在一个subprocess中捕获SIGTERM
,并且看起来没有被触发。 我的推测是Docker或Linux内核在closures容器使用的cgroup时发送了SIGKILL
,但是我没有发现有关文档的任何说明。
编辑最接近我来解释是从baseimagedocker以下报价:
如果您的init进程是您的应用程序,那么它可能只会closures它自己,而不是容器中的所有其他进程。 内核将强制杀死其他进程,而不是给予他们正常closures的机会,可能导致文件损坏,临时文件过时等。你真的想要优雅地closures所有的进程。
所以至less按照这个意思,这意味着当容器退出时,内核会发送一个SIGKILL给所有剩下的进程。 但是我还是想清楚它是如何决定这样做的(即它是cgroups的一个特征吗?),理想情况下,更权威的来源会更好。
好的,我似乎已经提出了一些更确凿的证据,实际上是Linux内核正在终止。 在clone(2)
手册页中,有这个有用的部分:
CLONE_NEWPID (自Linux 2.6.24起)
在新名称空间(即使用CLONE_NEWPID标志创建的进程)中创建的第一个进程具有PID 1,并且是名称空间的“init”进程。 在命名空间中孤儿的孩子将被重新设置到这个过程而不是init(8)。 与传统的init进程不同,PID命名空间的“init”进程可以终止,如果是的话,命名空间中的所有进程都将终止。
不幸的是,这对于名称空间中的进程究竟是如何终止仍然是模糊的,但也许这是因为,与正常的进程退出不同,进程表中没有任何条目。 无论如何,似乎很清楚: