在许多博客文章和一般意见中,有一种说法是“每个容器一个过程”。
为什么存在此规则?为什么不在需要所有进程都可以工作的单个容器中运行ntp,nginx,uwsgi和更多进程?
提到此规则的博客文章:
在许多博客文章和一般意见中,有一种说法是“每个容器一个过程”。
为什么存在此规则?为什么不在需要所有进程都可以工作的单个容器中运行ntp,nginx,uwsgi和更多进程?
提到此规则的博客文章:
Answers:
让我们暂时忘记高层的建筑和哲学争论。尽管在某些情况下单个容器中的多个功能可能有意义,但出于非常实际的原因,您可能需要考虑遵循“每个容器一个功能”的经验法则:
请注意,我说的是功能,而不是过程。该语言已过时。官方搬运工文档已经搬走了从说“一个过程”,而不是建议每个集装箱“一和关怀”。
几天前杀死了“两个进程”容器后,我感到有些痛苦,这使我使用了两个容器而不是启动两个进程的python脚本:
该建议来自操作系统级虚拟化的目标和设计
容器经过设计,可以通过为容器分配自己的用户空间和文件系统来使其隔离。
这是chroot
提供一个隔离的文件系统的逻辑演变,下一步是将进程与其他进程隔离,以避免内存覆盖,并允许多个进程使用相同的资源(例如TCP端口8080)而不会发生冲突。
容器的主要目的是将其打包为过程所需的库,而不必担心版本冲突。如果您在同一用户空间和文件系统中运行多个需要相同库的两个版本的进程,则必须为每个进程至少调整LDPATH,以便首先找到合适的库,并且某些库无法通过这种方式进行调整,因为它们的路径是在编译时在可执行文件中硬编码的,所以请参见此SO问题以获取更多详细信息。
在网络级别,您必须配置每个进程,以避免使用相同的端口。
在同一个容器中运行多个进程需要进行一些大的调整,最终最终无法达到隔离的目的,如果可以在同一用户空间中运行多个进程,共享相同的文件系统和网络资源,那为什么不运行它们在主机本身上?
这是我能想到的大量调整/陷阱的非详尽清单:
处理日志
无论是已装入的卷,还是在stdout上交错插入,都会带来一些管理。如果使用已安装的卷,则您的容器应在主机上拥有自己的“位置”,否则两个相同的容器将争夺相同的资源。如果docker logs
无法轻松识别源,则对stdout进行交错以利用它可能成为分析的噩梦。
当心僵尸进程
如果容器中的某个进程崩溃了,那么超级用户可能无法清理处于僵尸状态的子进程,并且主机初始化将永远不会继承它们。一旦用尽了可用的pid数(2 ^ 22大约为400万),一堆事情就会失败。
关注点分离
如果您在同一个容器中运行两个分开的东西,例如apache服务器和logstash,这可能会简化日志处理,但是您必须关闭apache来更新logstash。(实际上,您应该使用Docker的日志记录驱动程序)是否会优雅地停止等待当前会话结束?如果这是一个正常的停止,则可能需要一段时间并花费很长时间才能推出新版本。如果您采取了杀死措施,则会影响用户的日志发送者,因此应避免恕我直言。
最后,当您有多个进程时,您正在复制一个OS,在这种情况下,使用硬件虚拟化听起来更符合这种需求。
在大多数情况下,这不是全部或全部。“每个容器一个过程”的指导源于容器应用于不同目的的想法。例如,容器不应同时是Web应用程序和 Redis服务器。
在某些情况下,只要两个进程都支持单个模块化功能,就可以在单个容器中运行多个进程。