一.CMD命令
支持三种格式
- CMD ["executable","param1","param2"] 使用 exec 执行,推荐方式;
- CMD ["param1","param2"] 可以自己执行,也可以给 ENTRYPOINT 提供参数;
- CMD command param1 param2 在 /bin/sh 中执行,提供给需要交互的应用;
用法1:
带有中括号的形式。这时,命令没有在任何shell终端环境下,如果我们要执行shell,必须把shell加入到中括号的参数中。这种用法就像一个c语言的exec函数,意思是我们要执行一个进程。如果采用非shell的方法,那么上面的例子要修改
[root@server1 docker]# mkdir busybox
[root@server1 docker]# cd busybox
[root@server1 busybox]# vim Dockerfile
FROM busybox
ENV name world
CMD ["/bin/sh","-c","echo hello,$name"]
需要注意,采用中括号形式,那么第一个参数必须是命令的全路径才行。
官网推荐采用这种方法。
用法2:
FROM busybox
ENV name world
CMD ["/bin/echo","hello,$name"]
用法3:
即没有中括号的形式。那么命令comand默认是在“/bin/sh -c“下执行的。比如下面的dockerfile:
FROM busybox
ENV name world
CMD echo "hello,$name"
总结:
指定启动容器时执行的命令,每个 Dockerfile 只能有一条 CMD 命令。如果指定了多条命令,只有最后一条会被执行。
如果用户启动容器时候指定了运行的命令,则会覆盖掉 CMD 指定的命令。
二.ENTRYPOINT命令
支持两种格式:
ENTRYPOINT ["executable", "param1", "param2"] 推荐方式;
ENTRYPOINT command param1 param2(shell中执行)。
用法一:
[root@server1 docker]# mkdir busybox
[root@server1 docker]# cd busybox
[root@server1 busybox]# vim Dockerfile
FROM busybox
ENTRYPOINT ["/bin/echo","hello"]
CMD ["world"]
总结:
配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。
每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个起效。
三.总结
CMD指定的命令可以被docker run传递的命令覆盖,例如,如果用CMD指定:CMD ["echo"]
然后运行docker run CONTAINER_NAME echo foo,
那么CMD里指定的echo会被新指定的echo覆盖,所以最终相当于运行echo foo,所以最终打印出的结果就是:foo而ENTRYPOINT会把容器名后面的所有内容都当成参数传递给其指定的命令(不会对命令覆盖),比如:ENTRYPOINT ["echo"]
然后运行docker run CONTAINER_NAME echo foo,则CONTAINER_NAME后面的echo foo都作为参数传递给ENTRYPOING里指定的echo命令了,所以相当于执行了
echo "echo foo"
最终打印出的结果就是:
echo foo另外,在Dockerfile中,ENTRYPOINT指定的参数比运行docker run时指定的参数更靠前,比如:ENTRYPOINT ["echo", "foo"]
执行docker run CONTAINER_NAME bar,相当于执行了:echo foo bar
打印出的结果就是:foo bar
从上面的说明,我们可以看到有两个共同点:
- 都可以指定shell或exec函数调用的方式执行命令;
- 当存在多个CMD指令或ENTRYPOINT指令时,只有最后一个生效;
而它们有如下差异:
差异1:CMD指令指定的容器启动时命令可以被docker run指定的命令覆盖,而ENTRYPOINT指令指定的命令不能被覆盖,而是将docker run指定的参数当做ENTRYPOINT指定命令的参数。
差异2:CMD指令可以为ENTRYPOINT指令设置默认参数,而且可以被docker run指定的参数覆盖;