Ali
#1
不明白当我尝试在运行时通过CMD指令在`Dockerfile中执行两个命令时发生了什么。 我认为这应该工作:
CMD ["/etc/init.d/nullmailer", "start", ";", "/usr/sbin/php5-fpm"]
但它不起作用。 容器尚未启动。 所以我不得不这样做:
CMD ["sh", "-c", "/etc/init.d/nullmailer start ; /usr/sbin/php5-fpm"]
我不明白 这是为什么? 为什么第一行不是正确的方式? 有人可以解释我这些"CMD shell格式vs JSON格式等"的东西。 用简单的话来说。
只是要注意-同样是与 command:
指示 docker-compose.yml
,正如预期的那样。
Harley
#2
我相信区别可能是因为第二个命令做shell处理,而第一个没有。 每个 正式文件,有 exec
和 shell
表格。 你的第一个命令是 exec
表格。 该 exec
表单不展开环境变量,而 shell
形式确实如此。 这是可能的,通过使用 exec
表单命令由于依赖于shell处理而失败。 你可以通过运行来检查这一点 docker logs CONTAINERID
你的第二个命令,shell表单,相当于 -
CMD /etc/init.d/nullmailer start ; /usr/sbin/php5-fpm
文件摘录 -
注意:与shell窗体不同,exec窗体不会调用命令shell。 这意味着正常的shell处理不会发生。 例如, CMD [ "echo", "$HOME" ]
不会在上做变量替换 $HOME
. 如果你想要shell处理,那么要么使用shell表单,要么直接执行shell,例如: CMD [ "sh", "-c", "echo", "$HOME" ]
.
Gene_H
#3
别让自己为难。 只需创建一个bash文件"start.sh":
#!/bin/bash/usr/bin/command2 param1/usr/bin/command1
在你的Dockerfile do:
ADD start.sh /RUN chmod +x /start.shCMD ["/start.sh"]
的json语法 CMD
(和 RUN
和 ENTRYPOINT
)将参数作为exec syscall直接传递给内核。 在exec syscall中,没有用空格、引号转义、IO重定向、变量替换、命令之间的管道、运行多个命令等将命令与参数分开。 Syscall只需要运行可执行文件,并将参数列表传递给该可执行文件,然后运行它。
人物喜欢 $
展开变量, ;
分离命令,
(空格)分隔参数, &&
和 ||
链式命令, >
用于输出重定向, |
命令之间的管道等,都是shell的功能,需要类似的东西 /bin/sh
或 /bin/bash
来解释和实施它们。
如果切换到字符串语法 CMD
,docker会用shell运行你的命令:
CMD /etc/init.d/nullmailer start ; /usr/sbin/php5-fpm
否则,你的第二个语法做同样的事情:
CMD ["sh", "-c", "/etc/init.d/nullmailer start ; /usr/sbin/php5-fpm"]
请注意,我不建议在容器内以这种方式运行多个命令,因为如果第一个命令失败,特别是在后台运行,则没有错误处理。 您还会在容器内留下一个运行为pid1的shell,这将破坏信号处理,导致10秒的延迟和码头工人忘恩负义地杀死您的容器。 信号处理可以通过使用外壳来减轻 exec
命令:
CMD /etc/init.d/nullmailer start ; exec /usr/sbin/php5-fpm
但是,处理在后台静默失败的进程需要您切换到像supervisord这样的多进程管理器,或者最好将您的应用程序分解为多个容器并使用docker-compose之类的东西进行部署。
我猜first命令失败,因为在DOCKER CMD形式中,只执行第一个参数,其余部分被送入此命令。
第二种形式是有效的,因为所有与";"分开的命令都输入到sh命令中,由sh命令执行它们。
例如,假设你有两个python命令要运行 python init_reset.py
和 python app.py
. 然后使用CMD,您可以将两个命令与单个命令合并
CMD python init_reset.py ; python app.py
Maxx
#7
在Docker compose中,这可以通过以下示例完成:
command: ["sh", "-c", " apt update && apt install -y libldap-common; cp /ca.crt /usr/local/share/ca-certificates/; update-ca-certificates; exec apache2-foreground "]
该 exec
将主可执行文件的上下文切换到apache2-forground。
我不认为你应该在"开始"之后加上半逗号"
而不是使用
CMD ["/etc/init.d/nullmailer", "start", ";", "/usr/sbin/php5-fpm"]
试试
CMD ["/etc/init.d/nullmailer", "start", "/usr/sbin/php5-fpm"]
由于码头工人使用"sh-c",上述命令将按以下方式执行
/etc/init.d/nullmailer start/etc/init.d/nullmailer /usr/sbin/php5-fpm