为什么可以';我是否多次使用Docker CMD来运行多个服务?

为什么可以';我是否多次使用Docker CMD来运行多个服务?,docker,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 要启动rabbitmq容器,请运行: docker run -d -p 222:22 -p 4149:4149

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

然后我想构建一个映像,运行另一个名为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

  • CMD如何在docker图像中工作
  • 如果我想运行多个服务,如何运行?使用主管

  • 没错,第二个Dockerfile将覆盖第一个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
    

    尽管CMD写在Dockerfile中,但它实际上是运行时信息。与暴露一样,但与运行和添加相反。我的意思是,您可以稍后在扩展Dockerfile中覆盖它,或者在run命令中覆盖它,这就是您正在经历的。在任何时候,都只能有一个CMD

    如果您想运行多个服务,我确实会使用supervisor。您可以为每个服务创建一个管理器配置文件,将它们添加到一个目录中,并使用
    supervisor-c/etc/supervisor
    运行管理器,以指向一个管理器配置文件,该文件加载您的所有服务,看起来像

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

    如果你想了解更多细节,我在这里写了一篇关于这个主题的博客:

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

    真正回答你的问题“为什么”。。。我认为,了解
    docker stop
    命令的工作原理以及所有进程都应该干净地关闭,以防止在尝试重新启动时出现问题(文件损坏等),这将对您有所帮助

    问题:如果docker确实从其命令启动了SSH,并从docker文件启动了RabbitMQ,该怎么办?“”docker跟踪作为PID 1的哪个进程将获得SIGTERM?是宋承宪还是兔子

    答:Docker只需将最后一个CMD作为一个,它将作为根进程启动,PID为1,并从
    Docker stop
    获取SIGTERM

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

    值得注意的是,正是出于这个原因,从Docker 1.13及更高版本开始,tini正式成为Docker的一部分,这告诉我们在Docker中运行多个进程是有效的。。因此,即使有人认为Docker是荒谬的,并且坚持认为你这样做是荒谬的,但要知道你不是。这样做是完全有道理的

    很高兴知道:


      • 码头工人的官方回答

        它解释了如何使用init系统(systemd、sysvinit、upstart)、脚本(
        CMD./my\u wrapper\u script.sh
        )或类似于
        supervisord
        的管理器来完成此操作


        &&
        解决方案只能用于在后台启动的服务(守护进程)或在没有交互和释放提示的情况下快速执行的服务。使用交互式服务(保持提示)执行此操作时,只有第一个服务将启动。

        要解决为什么CMD设计为每个容器只运行一个服务的问题,让我们了解一下,如果在同一容器中运行的辅助服务器不是琐碎的/辅助的,而是“主要的”(例如,与前端应用程序捆绑的存储). 首先,它将分解几个重要的容器化功能,例如水平(自动)扩展和节点之间的重新调度,这两个功能都假定每个容器只有一个应用程序(CPU负载源)。然后是漏洞的问题-容器中暴露的服务器越多,意味着CVE的修补就越频繁

        因此,让我们承认,这是Docker(和Kubernetes/Openshift)设计师向良好实践的“推动”,我们不应该重新发明变通方法(SSH不是必需的-我们设计了
        Docker exec/kubectl exec/oc rsh
        来取代它)

        • 更多信息

        谢谢,我想使用主管是很重要的 更好。但是为什么docker只运行一个CMD?里面发生了什么?我不知道里面发生了什么。但我认为它就是这样设计的。当您有一个图像并在其中运行命令(例如,使用CMD)时,它会启动一个容器。只要命令运行,容器就会一直运行。一旦命令完成,容器也会停止。所以每个容器代表一个(正在运行的)命令。我想可能是因为lcx或其他原因limit@Tyguy7 .. ................ ?
        &&
        技术只适用于非交互式服务(可以在后台启动),否则只有第一个服务会运行。谢谢,主管是个好主意,但我想知道CMD在docker Imager中是如何工作的。你问了两个问题,2。关于运行多个服务。想知道CMD是如何工作的,请详细说明你想知道的具体内容。我已经提到它是运行时信息,并且被任何新的CMD覆盖。