Dockerfile CMD 指令将在运行后立即退出容器

Posted

技术标签:

【中文标题】Dockerfile CMD 指令将在运行后立即退出容器【英文标题】:Dockerfile CMD instruction will exit the container just after running it 【发布时间】:2017-07-02 07:38:09 【问题描述】:

我想在我的容器启动时设置一些配置,为此我使用的是 shell 脚本。但是我的容器将在我的脚本结束后立即退出,我尝试使用 -d 标志/分离模式,但它永远不会在分离模式下运行。

下面是我的 Dockerfile

FROM ubuntu:14.04

ADD shell.sh /usr/local/bin/shell.sh

RUN chmod 777 /usr/local/bin/shell.sh

CMD /usr/local/bin/shell.sh

下面是我的shell脚本

#!/bin/bash
echo Hello-docker

    不带任何标志运行

    docker run hello-docker
    

    这将在我的控制台上打印“Hello-docker”并退出

    使用 -itd 标志运行

    docker run -itd hello-docker
    

    如下所示,我的控制台输出,这一次也将很快退出。 :(

    我在 COMMAND 部分看到的不同之处在于,当我运行其他图像时,命令部分将显示“/bin/bash”,并将继续以分离模式运行。

    当我使用 shell 脚本在容器中运行映像时,COMMAND 部分将显示“/bin/sh -c /usr/loca”,然后退出。

    我想运行容器直到我不手动停止它。

编辑:

在 Dockerfile 中添加 ENTRYPOINT 指令后,这将不会执行我的 shell 脚本 :(

FROM ubuntu:14.04

ADD shell.sh /usr/local/bin/shell.sh

RUN chmod 777 /usr/local/bin/shell.sh

CMD /usr/local/bin/shell.sh

ENTRYPOINT /bin/bash

根据 docker 文档here

当使用替代参数运行容器时,CMD 将被覆盖,因此如果我使用以下一些参数运行 docker image,将不会执行 CMD 指令。 :(

sudo docker run -it --entrypoint=/bin/bash <imagename>

【问题讨论】:

【参考方案1】:

只要 Dockerfile 中的CMD 占用,docker 容器就会运行。

在您的情况下,您的 CMD 包含一个包含单个回显的 shell 脚本。所以容器会在完成回显后退出。

您可以覆盖CMD,例如:

sudo docker run -it --entrypoint=/bin/bash <imagename>

这将在您的容器中启动一个交互式 shell,而不是执行您的 CMD。您的容器将在您退出该 shell 后立即退出。

如果您希望您的容器保持活动状态,您必须确保您的 CMD 继续运行。例如,通过将行 while true; do sleep 1; done 添加到您的 shell.sh 文件中,您的容器将打印您的 hello 消息,然后在您停止它之前不再执行任何操作(在另一个终端中使用 docker stop)。

您可以使用docker exec -it &lt;containername&gt; bash 在正在运行的容器中打开一个shell。如果您随后执行命令ps ax,它将显示您的 shell.sh 仍在容器内运行。

【讨论】:

但这不会执行 CMD 指令,我的 shell 脚本不会被执行。 :( 没错。你不能两者兼得。唯一的其他选择是让您的CMD 继续运行。我在答案中添加了一个示例。 但是我也想执行我的脚本,我不想手动执行。这就是问题所在。【参考方案2】:

你也可以修改你的第一个 Dockerfile,替换

CMD /usr/local/bin/shell.sh

通过

CMD /usr/local/bin/shell.sh ; sleep infinity

这样,您的脚本不会终止,并且您的容器会继续运行。

【讨论】:

这会起作用,但在此之后如果我附加容器并想要检查一些东西它不会响应。就像如果执行 ls -l 命令什么都不会发生。 可以docker exec container_id__or_name ls -l代替attach 但我仍然觉得有一种更棒的方法来代替使用 ;无限睡眠。 你也可以在你的 CMD 中做一些事情,比如 bash -C '/path/to/start.sh';'bash' 这样,当你的脚本完成时,你有一个 shell,见 markbetz.net/2014/03/17/…【参考方案3】:

最后通过一些实验,我得到了最好的结果,如下所示

我的 Dockerfile 没有任何问题,如下所示是正确的。

FROM ubuntu:14.04

ADD shell.sh /usr/local/bin/shell.sh

RUN chmod 777 /usr/local/bin/shell.sh

CMD /usr/local/bin/shell.sh

为了得到预期的结果,我只需在我的 shell 脚本文件中添加一个命令(/bin/bash),如下所示,然后一切都以我最好的方式运行。

#!/bin/bash

echo “Hello-docker” > /usr/hello.txt

/bin/bash

【讨论】:

只在 dockerfile 中执行:RUN /bin/echo -e "#!/bin/bash\npython welcome.py\n/bin/bash" &gt; /usr/local/bin/onstartup.sh &amp;&amp; chmod 777 /usr/local/bin/onstartup.sh 然后CMD /usr/local/bin/onstartup.sh 谢谢阿南德,这对我有用。在我的情况下:# Create an executable file that starts the server... # A unix executable .sh-file must start with #!/bin/bash. '\n' means 'newline'. RUN printf '#!/bin/bash\n/etc/NX/nxserver --startup\n/bin/bash'"" &gt; /etc/NX/nxserverStart.sh # .. and make it actually executable ... RUN chmod +x /etc/NX/nxserverStart.sh # Start the nomachine-remote server when the container runs, and ... CMD ["/etc/NX/nxserverStart.sh"] 并使用docker run -d -t -p 4000:4000 --name 'linux_remote_pc' 'linux_remote_pc_image' 运行容器 天啊,你做的很简单。最佳答案!【参考方案4】:
CMD bash -C '/path/to/start.sh';'bash'

【讨论】:

虽然这段代码 sn-p 可以解决问题,including an explanation 确实有助于提高您的帖子质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。【参考方案5】:

在您的启动 shell 中添加一行代码: tail -f /dev/null/bin/bash 确保您完成外壳并暂停系统中的进程,以便 docker 容器不会关闭。不要忘记让“chmod +x”访问 start.sh。 有演示:

#!/bin/bash
cp /root/supervisor/$RUN_SERVICE.ini /etc/supervisor/conf.d/
sleep 1
service supervisor start
/bin/bash

【讨论】:

【参考方案6】:

试试

CMD /bin/bash -c 'MY_COMMAND_OR_SHELL_SCRIPT; /bin/bash'

在这里尝试对@lanni654321 的答案进行解释。 sh shell 在 Dockerfile 中是标准的。您必须调用bash shell 以使用.bashrc 启动bash,许多命令也需要RUN /bin/bash -c '...',方法与上面的CMD 相同,因为sh shell 通常是不够的。如果您在CMD 的末尾添加“bash”,则容器不会退出,因为提交的图像仍然处于打开状态。

有关由sh 引起并由bash 解决的错误,请参阅“/bin/sh: 1: MY_COMMAND: not found”。

我认为您通常不需要这个。您可以只使用RUN /bin/bash -c '...',在我的情况下,这可以在您进入docker-compose 中的不同细节以启动容器之前执行任何可以在基本映像中完成的操作。

但是,如果您只需要让一个容器运行而不退出,那么这一切都不需要。只是

docker run -dit --name MY_CONTAINER MY_IMAGE:latest

然后

docker exec -it MY_CONTAINER /bin/bash

你应该在容器的 bash 中,它不应该退出。

或者如果在docker-compose期间退出,使用

command: bash -c "MY_COMMAND --wait"

【讨论】:

以上是关于Dockerfile CMD 指令将在运行后立即退出容器的主要内容,如果未能解决你的问题,请参考以下文章

Dockerfile 指令

dockerfile指令汇总

Dockerfile指令详解

Dockerfile自作镜像

Docker Dockerfile 指令

Dockerfile 中的 CMD 与 ENTRYPOINT