【问题标题】:What happens to other processes when a Docker container's PID1 exits?当 Docker 容器的 PID1 退出时,其他进程会发生什么?
【发布时间】:2016-09-28 06:33:23
【问题描述】:

考虑以下,它在后台运行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,但我在任何地方都找不到任何文档来澄清这一点。

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

如果您的 init 进程是您的应用程序,那么它可能只会自行关闭,而不是容器中的所有其他进程。然后内核将强行杀死那些其他进程,而不给它们正常关闭的机会,这可能会导致文件损坏、过时的临时文件等。您真的想优雅地关闭所有进程。

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

【问题讨论】:

    标签: linux docker cgroups


    【解决方案1】:

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

    CLONE_NEWPID(自 Linux 2.6.24 起)

    在新命名空间中创建的第一个进程(即进程 使用 CLONE_NEWPID 标志创建的)具有 PID 1,并且是 命名空间的“init”进程。成为孤儿的孩子 命名空间内将被重新分配给这个进程,而不是 初始化(8)。不同于传统的init进程,一个“init”进程 PID 命名空间可以终止,如果终止,所有进程 命名空间已终止。

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

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

    【讨论】:

    • 如果你是running in the hosts pid namespace,码头工人runc 可以进行清理。
    • 内核确实发送了SIGKILL 来终止进程。
    • @Matt 很高兴知道。是否成为主机init 进程的责任来获取这些,或者内核是否也将它们从进程表中删除?
    • 当 docker 容器进程 (docker run --pid host) 上没有 NEWPID 选项时,内核无法自行删除/杀死进程。如果 Docker 没有设法使用该代码清理它们,这些进程将继承系统 PID 1 作为父进程,并可能成为僵尸。
    猜你喜欢
    • 1970-01-01
    • 2019-02-11
    • 2015-02-26
    • 2017-06-12
    • 2013-10-13
    • 1970-01-01
    相关资源
    最近更新 更多