CMD
(和RUN
和ENTRYPOINT
)的json语法将参数直接作为exec syscall传递给内核。在exec syscall中,命令与参数之间没有空格,引号转义,IO重定向,变量替换,命令之间的管道传递,运行多个命令等之间的分隔。syscall仅使可执行文件运行,并将参数列表传递给该可执行文件,然后运行它。
字符,如$
扩大变量,;
以单独的命令,
(空间)分开的争论,&&
并||
以链的命令,>
输出重定向,|
以命令之间的管道等,都是壳和需要像所有功能/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"]
请注意,我不建议您在容器内部以这种方式运行多个命令,因为如果您的第一个命令失败(特别是在后台运行),则不会进行错误处理。您还将在容器内留下一个以pid 1运行的外壳,这将中断信号处理,从而导致10秒的延迟,并被docker恶意破坏您的容器。使用shell exec
命令可以减轻信号处理:
CMD /etc/init.d/nullmailer start ; exec /usr/sbin/php5-fpm
但是,如果要在后台静默处理失败的进程,则需要切换到某种类型的多进程管理器(例如supervisor),或者最好将您的应用程序分解为多个容器,并使用诸如docker-compose之类的方式部署它们。
exec
表格,因为它是首选表格吗?为什么首选它?还是应该使用更简单的shell
形式?