在docker使用主pipe
我并不是要求与docker工使用监督员,而只是想让我的理解得到validation。
我知道docker在运行时运行一个进程。 另外,当我们需要在容器中运行多个进程时使用监督器。
我已经看到了几个例子,其中一个容器是从基本映像启动的,几个服务被安装,并且容器承诺形成一个新的映像,全部没有pipe理员。
所以,我基本的疑问是两种方法之间有什么区别。
我的理解是,当docker容器停止时,它向PID 1的进程发送一个kill信号,PID 1pipe理subprocess,并停止所有的subprocess,正如监督员完成的那样,而我们可以安装多进程,当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 – 有一个特殊的任务。 它的任务是“采用”孤儿过程。
操作系统期望init进程也收获收养孩子。
Docker问题:
我们看到很多人在他们的容器中只运行一个进程,他们认为当他们运行这个单一进程时,他们就完成了。
但是最有可能的是,这个过程并不像一个正确的初始化过程。
也就是说,不是恰当地收获所采用的stream程,而是期待另一个init
stream程来完成这个工作。
使用像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来转发信号和收获进程