CMD
CMD
指令有三种形式。
CMD ["executable","param1","param2"]
(exec 形式,这是一种最好的形式)。CMD ["param1","param2"]
(作为ENTRYPOINT的默认参数)。CMD command param1 param2
(shell 形式)。
在Dockerfile
中只能有一个CMD
命令。如果你写了多个CMD
命令,那么只有最后一个会生效。
CMD
的目的是为容器运行提供默认值,这些默认值可以包含一个可执行文件,或者他们可以省略可执行文件,
在这种情况下,你必须指定一个ENTRYPOINT
。
注意:如果
CMD
指令用于向ENTRYPOINT
指令提供默认参数,那么CMD
和ENTRYPOINT
指令都应该使用JSON 数组的形式。注意:exec形式会被解析为一个JSON 数组,这意味着你必须使用双引号包含单词而不是单引号。
注意:exec形式不同于shell形式,他不会启动一个命令行。意味着一般的shell处理是不会发生的。例如,CMD [ "echo", "$HOME" ]的HOME是不会发生变量替换的。如果你希望通过shell去处理一些事情时,你可以使用shell形式的RUN或者直接执行一个shell,CMD [ "sh", "-c", "echo $HOME" ]。当使用exec形式直接执行一个shell时和shell形式一样,他会是环境变量扩展的shell,而不是docker的。
当使用ENTRYPOINT或者exec形式时,CMD
指令设置了镜像运行时要执行的命令。
如果你使用shell形式,那么<command>
会在/bin/sh -c
中执行:
FROM ubuntu
CMD echo "This is a test." | wc -
如果你想要你不想要你的<command>
在shell中执行,那么你必须要使用JSON数组的形式,并且给出完整的可执行路径。数组形式是CMD
的最佳形式。任何其他参数必须表示为数组中的字符串:
FROM ubuntu
CMD ["/usr/bin/wc","--help"]
如果你希望你的容器每次运行相同的可执行文件,那么你应该考虑使用ENTRYPOINT
和CMD
指令。看一下 ENTRYPOINT。
如果用户在docker run
中指定了默认的参数,那么他们会覆盖CMD里的值。
注意:不要把
RUN
和CMD
混淆。RUN
实际上是执行一个命令,然后提交它;但是CMD不会执行任何东西在build的过程当中,而是指定以后容器的启动指令。