其实两者的关系,一图以蔽之,无非两个不同参数的排列组合。
首先看
ENTRYPOINT exec_entry p1_entry
,你会发现
CMD
根本不起作用,最后的结果都是
/bin/sh -c exec_entry p1_entry
-
如果没有
ENTRYPOINT
,则完全根据
CMD
来 -
shell form
:
CMD
完全失效 -
exec form
:
CMD
作为
ENTRYPOINT
的参数
上面的排列组合有很多是错误的,建议使用框中的方式。
CMD
CMD
有三种形式
-
CMD ["executable","param1","param2"]
(
exec
form, this is the preferred form) -
CMD ["param1","param2"]
(as
default parameters to ENTRYPOINT
) -
CMD command param1 param2
(
shell
form)
每个
Dockerfile
中只有一个
cmd
,如果填了多个,只有最后一个会生效。这个同样适用于
ENTRYPOINT
。
CMD
的主要作用是给容器提供
默认启动方式
,这种默认启动方式可以包含一个
可执行体
,或者通过指定
ENTRYPOINT
来充当可执行体。
为什么叫默认启动方式,就是因为我们在启动容器时后面都会跟个命令
docker run img cmd
,如果没跟命令,那么容器就是用
Dockerfile
指定的
CMD
,如果提供了命令就把它覆盖掉。
这里的可执行体可以是
shell
,也可以是可执行文件。
如下只有最后一个是正确的,第二个也不会出错,但不会有期望的输出。
-
CMD [“echo $HOME”] 可执行体错误 -
CMD [“echo”, “$HOME”] 打印结果为
$HOME
, 因为没有指定
shell
-
CMD [“sh”, “-c”, “echo”, “$HOME”]
shell
后面需跟整个字符串,不能分成多个 -
CMD [“sh”, “-c”, “echo $HOME”]
如果
cmd
当做
ENTRYPOINT
的执行参数,那
CMD
和
ENTRYPOINT
都应该指定为
JSON array
形式,也就是带括号形式。
既然是
JSON array
形式,那么只能使用双引号,不能使用单引号。
如果用
shell
形式的
CMD
,那默认的可执行体就是
/bin/sh -c
ENTRYPOINT
ENTRYPOINT
有两种形式
-
ENTRYPOINT ["executable", "param1", "param2"]
(exec form, this is the preferred form) -
ENTRYPOINT command param1 param2
(shell form)
这两种方式跟
CMD
一模一样。
剩下就是两者的组合问题了。