在docker使用主pipe

我并不是在问Docker的主pipe,而只是想让我的理解得到validation。

我知道docker在运行时运行一个进程。 另外,当我们需要在容器中运行多个进程时使用监督器。

我已经看到了几个例子,其中一个容器是从基本映像启动的,并且安装了几个服务,并且容器承诺形成一个新的映像,全部没有pipe理员。

所以,我基本的疑问是两种方法之间有什么区别。

我的理解是,当docker容器被停止时,它向PID 1的进程发送一个kill信号,PID 1pipe理subprocess,并停止所有的subprocess,而supervisor完成的则是我们可以安装多进程,当docker run发出时,进程可以运行,当container停止时,只有PID 1发送信号,其他运行进程不会被正常停止。

请确认我对使用supervisord的理解是否正确。

谢谢

我们可以在没有pipe理员的情况下安装多个进程,在发出docker运行和容器停止时,只有一个进程可以运行,只有PID1发送信号,其他运行进程不会被正常停止。

是的,虽然这取决于你的主stream程如何运行(前台或后台),以及如何收集subprocess。

这就是“ 在Docker容器中捕获信号 ”

docker stop通过发送SIGTERM信号停止一个正在运行的容器,让主进程处理它,在宽限期之后使用SIGKILL终止应用程序。

发送到容器的信号由正在运行的主进程(PID 1)处理。

如果应用程序在前台,意味着应用程序是容器中的主进程(PID1),它可以直接处理信号。

但:

要发送信号的过程可以是背景信号,不能直接发送任何信号。 在这种情况下,一个解决scheme是设置一个shell脚本作为入口点,并编排该脚本中的所有信号处理。

这个问题在“ Docker和PID 1僵尸收获问题 ”

Unix的devise方式是父进程必须显式“等待”subprocess终止,以便收集其退出状态。 僵尸进程一直存在,直到父进程执行此操作,使用waitpid()系列调用系列。

为了消除它的僵尸,在subprocess上调用waitpid()的行为被称为“收获”。

init进程 – PID 1 – 有一个特殊的任务。 它的任务是“采用”孤儿过程。

https://blog.phusion.nl/wp-content/uploads/2015/01/adoption.png

操作系统期望init进程也收获收养孩子。

Docker问题:

我们看到很多人在他们的容器中只运行一个进程,他们认为当他们运行这个单一进程时,他们就完成了。
但是最有可能的是,这个过程并不像一个正确的初始化过程。
也就是说,不是恰当地收获所采用的stream程,而是可能期望另一个initstream程来完成这个工作。

使用像phusion/baseimage-docker这样的图像可以帮助pipe理一个(或几个)进程,同时保持主进程兼容。

它使用runit而不是supervisord进行多进程pipe理:

Runit不是为了解决收割问题。 相反,它支持多个进程。 鼓励多个进程的安全性(通过进程和用户隔离)。
Runit使用比Supervisord更less的内存,因为Runit是用Python编写的,Supervisord是用Python编写的。
而在某些使用情况下,容器中的进程重新启动优于整个容器重新启动。

该映像包含一个my_init脚本 ,用于处理“收获”问题。

在baseimage-docker中,我们鼓励在一个容器中运行多个进程。 虽然不一定是多个服务。
逻辑服务可以由多个操作系统进程组成,我们提供的设施可以轻松实现。

Docker 1.12 2016年9月更新(2016年第四季度/ 2017年第一季度)

Arnaud Porterie只是嘲笑 :

[🐳]刚合并: docker run --init , Rick Grimes会照顾你所有的僵尸。

( 犯eabae09 )

参见PR 26061 :“ 为僵尸战斗和信号处理添加初始化过程 ”(和PR 26736 )

这增加了一个小C的二进制战斗僵尸。 它被挂载在/ dev / init下,并被用户指定的参数所预置。 你可以通过一个守护进程标志dockerd –init来启用它,因为它是默认禁用向后兼容的。

您也可以覆盖守护程序选项,或者使用docker run --init=true|false在每个容器的基础上指定此选项。

你可以通过运行一个像这样的进程来testing容器中的pid 1,并查看容器运行时出现的额外的僵尸。

 int main(int argc, char ** argv) { pid_t pid = fork(); if (pid == 0) { pid = fork(); if (pid == 0) { exit(0); } sleep(3); exit(0); } printf("got pid %d and exited\n", pid); sleep(20); } 

docker守护程序现在有选项

 --init 

在容器中运行一个init来转发信号和收获进程