RUN vs CMD vs ENTRYPOINT
- RUN:执行命令并创建新的镜像层;
- CMD:设置容器启动后默认执行的命令即参数,但cmd能被docker run后面的命令行参数替换;
- ENTRYPOINT:配置容器启动时运行的命令。
shell和Exec格式
shell格式
<instruction> <command>
例如:
RUN apt-get install python3
CMD echo "Hello world"
ENTRYPOINT echo "Hello world"
当命令执行时,shell格式的底层实际会调用/bin/sh -c [command]。例如:
ENV name docker
ENTRYPOINT echo "Hello, $name"
执行docker run [image]将输出:
Hello, docker
注意:shell会解析环境变量,环境变量name已经替换为值Cloud Man.
Exec格式
<instruction> ["executable", "param1", "param2", ...]
例如:
RUN ["apt-get", "install", "python3"]
CMD ["/bin/echo", "Hello world"]
ENTRYPOINT ["/bin/echo", "Hello world"]
当指令执行时,会直接调用[command]命令,不会被shell解析。
执行
ENV name docker
ENTRYPOINT ["/bin/echo", "hello, $name"]
运行容器将输出:
Hello, $name
注意环境变量name没有被替换。如果希望使用环境变量需要做如下修改Dockerfile:
ENV name cloud Man
ENTRYPOINT ["/bin/sh", "-c", "echo hello, $name"]
运行容器将输出:
Hello, docker
注意:CMD和ENTRYPOINT推荐exec格式,因为指令可读性更强,更容易理解。RUN则两种格式都可以。
RUN
RUN指令在当前镜像的顶部执行命令,并创建新的镜像层, Dockerfile中可以有多个RUN指令。注意,一个RUN指令可以运行多个命令,之间用&&符号隔开,这样只生成一层镜像层。特别是apt-get update && apt-get install要放在一个RUN指令中,这样保证每次安装的都是最新的包,如果分开,apt-get update创建的镜像层很可能是以前缓存的,不再是最新的。
CMD
CMD指令允许用户指定容器的默认执行的命令。
此命令会在容器启动且docker run没有指定其他命令是运行。
CMD有三种格式:
- Exec格式:CMD [“executable”, “param1”, “param2”]
- CMD [“param1”, “param2”]为ENTRYPOINT提供额外的参数,此时ENTRYPOINT必须使用Exec格式。
- shell 格式: CMD command param1 param2
第二种格式CMD [“param1”, “param2”]要与Exec格式的ENTRYPOINT指令配合使用,其用途是为ENTRYPOINT设置默认的参数。
举例:
Dockerfile片段:
CMD echo "Hello world"
运行容器 docker run -ti [image]将输出:
Hello world
当后面加上一个命令,比如docker run -ti [image] /bin/bash, CMD会被忽略掉,命令bash将被执行
root@10a32dc7d3d3:/#
ENTRYPOINT
ENTRYPOINT指令可以让容器以应用程序或者服务的形式运行。和CMD不同的是,ENTRYPOINT不会被忽略,一定会被执行,即使运行docker run时指定了其他命令。
两种格式:
- Exec格式:ENTRYPOINT [“executable", “param1”, “param2”],推荐格式;
- shell格式:ENTRYPOINT command param1 param2
Exec格式
ENTRYPOINT的Exec格式用于设置要执行的命令及其参数,同时可以通过CMD提供额外的参数。ENTRYPOINT中的参数始终会被用到,而CMD的额外参数可以再容器启动时动态替换。
例如:
ENTRYPOINT ["/bin/echo", "Hello"]
CMD ["world'"]
当容器通过docker run -ti [image]启动时,输出为:
Hello world
而如果通过docker run -ti [image] docker 启动,则输出为:
Hello docker
其中Dockerfile中CMD的默认参数world被docker run中的参数docker替换了。docker run中参数的优先级高于CMD的参数。
shell格式
ENTRYPOINT的shell格式会忽略任何CMD或docker run提供的参数。