为什么我不能多次使用Docker CMD来运行多个服务?

edw*_*ean 78 docker

我已经从Dockerfile构建了一个名为centos + ssh的基本映像.在centos + ssh的Dockerfile中,我使用CMD来运行ssh服务.

然后我想构建一个运行其他服务的图像,名为rabbitmq,Dockerfile:

FROM centos+ssh
EXPOSE 22
EXPOSE 4149
CMD /opt/mq/sbin/rabbitmq-server start
Run Code Online (Sandbox Code Playgroud)

要启动rabbitmq容器,请运行:

docker run -d -p 222:22 -p 4149:4149 rabbitmq
Run Code Online (Sandbox Code Playgroud)

但ssh服务不起作用,感觉rabbitmq的Dockerfile CMD覆盖了centos的CMD.

  1. CMD如何在docker图像中工作?
  2. 如果我想运行多个服务,怎么办?使用主管?

Tho*_*rig 102

你是对的,第二个Dockerfile将覆盖CMD第一个Dockerfile的命令.Docker将始终运行单个命令,而不是更多.因此,在Dockerfile的末尾,您可以指定一个要运行的命令.不多.

但是你可以在一行中执行两个命令:

FROM centos+ssh
EXPOSE 22
EXPOSE 4149
CMD service sshd start && /opt/mq/sbin/rabbitmq-server start
Run Code Online (Sandbox Code Playgroud)

你还可以做些什么来使你的Dockerfile更清洁,你可以将你的CMD命令放到一个额外的文件:

FROM centos+ssh
EXPOSE 22
EXPOSE 4149
CMD sh /home/centos/all_your_commands.sh
Run Code Online (Sandbox Code Playgroud)

和这样的文件:

service sshd start &
/opt/mq/sbin/rabbitmq-server start
Run Code Online (Sandbox Code Playgroud)

  • `&&` 技术仅适用于非交互式服务(可以在后台启动),否则只有第一个服务会运行。 (4认同)
  • 我不知道里面发生了什么。但我认为它就是这样设计的。当您拥有一个映像并在其中运行命令(例如使用 CMD)时,它会启动一个容器。只要命令运行,容器就会运行。一旦命令完成,容器也会停止。所以每个容器代表一个(正在运行的)命令。 (2认同)
  • @ Tyguy7 .. [因为](http://seethrumag.com/wp-content/uploads/2016/09/BUT-WHY-meme-45000-300x157.jpg)............ ....? (2认同)

qkr*_*ger 58

即使CMD写在Dockerfile中,它确实是运行时信息.就像EXPOSE一样,但与例如RUN和ADD相反.通过这个,我的意思是你可以稍后在扩展的Dockerfile中覆盖它,或者在你运行的命令中简单地覆盖它,这正是你所经历的.在任何时候,只能有一个CMD.

如果你想运行多个服务,我确实会使用主管.您可以为每个服务创建一个超级用户配置文件,在目录中添加这些文件,然后运行超级supervisord -c /etc/supervisor用户指向一个加载所有服务的超级用户配置文件,看起来像

[supervisord]
nodaemon=true

[include]
files = /etc/supervisor/conf.d/*.conf
Run Code Online (Sandbox Code Playgroud)

如果你想了解更多细节,我在这里写了一篇关于这个主题的博客:http://blog.trifork.com/2014/03/11/using-supervisor-with-docker-to-manage-processes-supporting-image-遗产/

  • 你问了两个问题,2.关于运行多个服务.在想知道CMD如何工作时,请详细说明您想要具体了解的内容.我已经提到它是运行时信息并被任何新的CMD覆盖. (2认同)

Mik*_*keM 24

虽然我尊重qkrijger的答案,解释如何解决这个问题,但我认为我们可以了解更多关于这里发生了什么......

要真正回答你的" 为什么 "的问题...我认为这对你有用的理解docker stop命令的工作原理以及所有进程应该干净地关闭以防止在你尝试重启它们时出现问题(文件损坏等).

问题:如果码头工人没有从它的命令来启动SSH 从码头工人开始RabbitMQ的文件?" docker stop命令首先尝试通过向容器中的根进程(PID 1)发送SIGTERM信号来停止正在运行的容器. "哪个进程是docker跟踪为PID 1,它将获得SIGTERM?它会是SSH还是兔子?"根据Unix进程模型,init进程 - PID 1 - 继承所有孤立的子进程并且必须收获它们.大多数Docker容器没有正确执行此操作的init进程,因此他们的容器被填充僵尸进程随着时间的推移."

答:泊坞窗简单地取,去年CMD作为一个将得到推出,根进程与PID 1,并从SIGTERM docker stop.

建议的解决方案:您应该使用(或创建)专门用于运行多个服务的基本映像,例如phusion/baseimage

重要的是要注意tini完全存在于这个原因,并且从Docker 1.13开始,tini正式成为Docker的一部分,它告诉我们在Docker中运行多个进程是有效的.所以即使有人声称对Docker 更熟练,坚持认为你这样做是荒谬的,知道你不是.这样做有完全有效的情况.

很高兴知道:


nor*_*raj 5

在容器中运行多个服务的官方 docker 答案。

它解释了如何使用 init 系统(systemd、sysvinit、upstart)、脚本 ( CMD ./my_wrapper_script.sh) 或类似supervisord.

&&解决方法仅适用于在后台启动的服务(守护进程)或无需交互即可快速执行并释放提示的服务。使用交互式服务(保持提示)执行此操作,并且只有第一个服务将启动。