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

我从Dockerfile中build立了一个名为centos + ssh的基础镜像。 在centos + ssh的Dockerfile中,我使用CMD来运行ssh服务。

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

FROM centos+ssh EXPOSE 22 EXPOSE 4149 CMD /opt/mq/sbin/rabbitmq-server start 

要启动rabbitmq容器,请运行:

 docker run -d -p 222:22 -p 4149:4149 rabbitmq 

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

  1. CMD如何在Docker镜像中工作?
  2. 如果我想运行多个服务,如何? 使用主pipe?

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

如果你想运行多个服务,我确实会使用主pipe。 您可以为每个服务创build一个主pipeconfiguration文件,将这些configuration文件添加到一个目录中,然后使用supervisord -c /etc/supervisor运行该supervisord -c /etc/supervisor以指向一个主pipeconfiguration文件,该configuration文件将加载所有服务并且看起来像

 [supervisord] nodaemon=true [include] files = /etc/supervisor/conf.d/*.conf 

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

你是对的,第二个Dockerfile会覆盖第一个的CMD命令。 Docker将始终运行一个命令,而不是更多。 所以在你的Dockerfile结尾,你可以指定一个命令来运行。 不多。

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

 FROM centos+ssh EXPOSE 22 EXPOSE 4149 CMD service sshd start && /opt/mq/sbin/rabbitmq-server start 

你还可以做些什么来使你的Dockerfile变得更干净,你可以把你的CMD命令放到一个额外的文件中:

 FROM centos+ssh EXPOSE 22 EXPOSE 4149 CMD sh /home/centos/all_your_commands.sh 

像这样的文件:

 service sshd start & /opt/mq/sbin/rabbitmq-server start 

虽然我尊重qkrijger解释如何解决这个问题的答案,但我认为还有很多我们可以了解到这里发生了什么…

要真正回答你的问题“ 为什么 ”…我认为这将有助于你了解docker stop命令是如何工作的,并且所有进程都应该干净地closures,以防止在你尝试重新启动时出现问题(文件损坏等) 。

问题:如果docker从它的命令启动了SSH, 从Docker文件启动了RabbitMQ,该怎么办? “ docker stop命令试图通过向容器中的根进程(PID 1)发送一个SIGTERM信号来首先停止一个正在运行的容器。 ”Docker跟踪哪个进程作为PID 1来获取SIGTERM? 会是SSH还是兔子? “根据Unix进程模型,init进程 – PID 1 – inheritance所有孤儿subprocess并且必须收获它们。大多数Docker容器没有正确的init进程,结果它们的容器被填充僵尸进程随着时间的推移“。

答案:Docker只需要将最后一个CMD作为以PID 1作为根进程启动的CMD,并从docker stop获取SIGTERM。

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

很高兴知道: