Dockerfile 中 RUN、ENTRYPOINT 与 CMD 的区别

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的参数。

5b95a43b0368eeca716077910c8fe95d.png

shell格式

ENTRYPOINT的shell格式会忽略任何CMD或docker run提供的参数。

猜你喜欢

转载自blog.csdn.net/cbmljs/article/details/90751011
今日推荐