Dockerfile的命令中包含ENTRYPOINT和CMD,使用ENTRYPOINT或者CMD,都可以达到让容器run起来的目的,但他们之间如何区分和选择呢?
CMD命令是一个容器的默认可执行体,也就是说容器启动之后默认会执行CMD的命令。我们在使用docker run时如果没有指定任何可执行命令并且Dockerfile里面业没有ENTRYPOINT,那么就会使用CMD指定的命令作为默认执行命令。
CMD有以下三种使用凡事
CMD ["program", "arg1", "arg2", ...]
带有中括号的形式。这时,命令没有再任何shell终端环境下,如果我们要执行shell,必须把shell加入到中括号的参数中。这种用法就像一个c语言的exec函数,意思是我们要执行一个进程。如果采用非shell的方法,那么上面的例子要修改为:
FROM centos
CMD ["/bin/bash", "-c", "echo 'Hello Docker CMD!'"]
该种形式需要注意,在指定可执行程序时,需要指定全路径,而且一个Dockerfile中最多只能有一个CMD命令,如果写了多个,只有最后一个会生效。
CMD command arg1 arg2 ...
如果是这种形式,则不需要将bash显示指定,例如:
FROM centos
CMD echo 'Hello Docker CMD!'
CMD ["args1", "arg2", ...]
CMD命令的行为在使用docker run命令的时候可以指定执行的命令去覆盖它,例如:
docker run xxx echo 'hello docker!'
ENTRYPONT是容器启动以后的真正的执行体,这也是官方推荐的使用方式。它有两种使用表现形式
ENTRYPOINT ["program", "arg1", "arg2", ...]
ENTRYPOINT command arg1 arg2 ...
这种方式可以结合CMD的第三种方式使用,例子如下:
FROM centos
CMD ["cmd args"]
ENTRYPOINT ["echo"]
在运行该Dockerfile生成的image时,如果docker run不指定参数,则会打印出cmd args,如果docker run指定了参数,则会打印出指定的参数
这种方式会直接指定死执行的命令和参数,无法在后期通过docker run修改,同时它无法与CMD混合使用,例如
FROM centos
CMD ["xxx"]
ENTRYPOINT echo
运行该Dockerfile生成的image,则不会打印出任何东西,即使在docker run显示指定参数也不会被打印出来。
ENTRYPOINT + CMD 组成Docker容器的命令,分别使用ENTRYPOINT的第一种方式和CMD的第三种方式组合使用为最佳实践,当docker run不指定参数时使用CMD指定的参数(默认参数),当指定参数时,使用指定的参数。
注:ENTRPOINT也是可以在运行时被重置的,使用
docker run
的--entrypoint
参数即可