我不是在询问使用码头工人的主管,而只是想让我的理解得到验证。
我知道docker在运行时会运行一个进程。此外,当我们需要在容器中运行多个进程时,使用超级用户。
我见过几个例子,其中从基本映像启动容器并安装了几个服务,并且容器被提交以形成新映像,所有这些都没有主管。
所以,我的基本疑问是两种方法之间的区别。
我的理解是当docker容器停止时它会向PID进程发送一个kill信号,PID 1管理子进程并停止所有的子进程,这正是supervisor所做的,而我们可以安装多个进程而不用管理员只有一个进程可以在 docker run 发出时运行,当容器停止时,只有PID 1将被发送信号,其他正在运行的进程将不会正常停止。
请确认我对使用supervisord的理解是否正确。
由于
答案 0 :(得分:49)
虽然我们可以在没有主管的情况下安装多个进程,但只有一个进程可以在发布docker run时运行,当容器停止时,只有PID 1将被发送信号,而其他正在运行的进程将不会正常停止。
是的,虽然它取决于主进程的运行方式(前台或后台),以及它如何收集子进程。
这是" Trapping signals in Docker containers"
中详细说明的内容
docker stop
通过发送SIGTERM
信号来停止正在运行的容器,让主进程处理它,并在宽限期后使用SIGKILL
来终止应用程序。发送到容器的信号由正在运行的主进程(PID 1)处理。
如果应用程序位于前台,意味着应用程序是容器(PID1)中的主要进程,它可以直接处理信号。
可是:
要发信号的过程可能是背景过程,您无法直接发送任何信号。在这种情况下,一种解决方案是将shell脚本设置为入口点,并编排该脚本中的所有信号处理。
问题在" Docker and the PID 1 zombie reaping problem"
中有详细说明Unix的设计方式是父进程必须明确地等待"对于子进程终止,以收集其退出状态。僵尸进程一直存在,直到父进程使用
waitpid()
系列调用执行此操作。在子进程上调用waitpid()以消除其僵尸的动作称为"收割"。
init
进程 - PID 1 - 有一项特殊任务。它的任务是采用"孤儿加工。
操作系统也希望init进程能够收获被收养的孩子。
Docker问题:
我们看到很多人只在他们的容器中运行一个进程,他们认为当他们运行这个单一进程时,他们就完成了。
但最有可能的是,这个过程并不像正确的初始化过程那样。
也就是说,而不是正确地收获所采用的流程,它可能期望另一个init
流程来完成这项工作,这是正确的。
使用像phusion/baseimage-docker
这样的图像来帮助管理一个(或几个)进程,同时保持主进程符合init。
它使用runit
instead of supervisord
进行多进程管理:
Runit不能解决收割问题。相反,它支持多个流程。鼓励多个流程实现安全性(通过流程和用户隔离) Runit使用的内存少于Supervisord,因为Runit是用C编写的,而Supervisord是用Python编写的 在某些用例中,容器中的进程重新启动优于整个容器重新启动。
该图片包含一个my_init
script,负责收集"收获"问题。
在baseimage-docker中,我们鼓励在单个容器中运行多个进程。但不一定是多种服务 逻辑服务可以包含多个操作系统进程,我们提供了轻松实现的功能。
答案 1 :(得分:16)
2016年9月更新docker 1.12(2016年第4季度/ 2017年第1季度)
[]刚刚合并:
docker run --init
,Rick Grimes会照顾你所有的僵尸。
请参阅PR 26061:" 为僵尸战斗和信号处理添加初始化过程" (和PR 26736)
这为战斗僵尸增加了一个小C二进制文件。它安装在 / dev / init并添加到用户指定的args之前。您 通过守护程序标志dockerd --init启用它,因为它被禁用 默认为向后兼并。
您还可以覆盖守护程序选项或在per上指定 以
docker run --init=true|false
为基础的容器基础。你可以通过运行像这样的进程来测试它,作为a中的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 daemon现在有选项
--init
在容器内运行init以转发信号并收集进程
答案 2 :(得分:0)
Docker文档中的这篇文章展示了一个示例,该示例运行多个进程并同时使用supervisor。
https://docs.docker.com/config/containers/multi-service_container/
我的工作很好,但是我们很可能会简单地将工作进程卸载到另一个容器中,而每个容器只处理一个进程。 此时感觉很简单。