第 3 章 镜像 - 017 - RUN vs CMD vs ENTRYPOINT

RUN、CMD 和 ENTRYPOINT 这三个 Dockerfile 指令看上去很类似,很容易混淆。

简单的说:

RUN 执行命令并创建新的镜像层,RUN 经常用于安装软件包。

CMD 设置容器启动后默认执行的命令及其参数,但 CMD 能够被 docker run 后面跟的命令行参数替换。

ENTRYPOINT 配置容器启动时运行的命令。

 

Shell 和 Exec 格式

可以用两种方式指定 RUN、CMD 和 ENTRYPOINT 要运行的命令:Shell 格式和 Exec 格式,二者在使用上存在细微的区别。

Shell 格式

<instruction> <command>

例如:

RUN apt-get install python3  

CMD echo "Hello world"  

ENTRYPOINT echo "Hello world" 

当指令执行时,shell 格式底层会调用 /bin/sh -c <command>。

例如下面的 Dockerfile 片段:

1 ENV name xxx  
2 ENTRYPOINT echo "Hello, $name" 


执行 docker run <image> 将输出:

Hello, xxx

注意环境变量 name 已经被值 xxx 替换。

 

Exec 格式

 <instruction> ["executable", "param1", "param2", ...]

例如:

1 RUN ["apt-get", "install", "python3"]  
2 CMD ["/bin/echo", "Hello world"]  
3 ENTRYPOINT ["/bin/echo", "Hello world"]

当指令执行时,会直接调用 <command>,不会被 shell 解析。


以Dockerfile 片段为例:

1 ENV name xxx  
2 ENTRYPOINT ["/bin/echo", "Hello, $name"] 

运行容器将输出:

Hello, $name

注意环境变量“name”没有被替换。
如果希望使用环境变量,照如下修改

1 ENV name xxx 
2 ENTRYPOINT ["/bin/sh", "-c", "echo Hello, $name"]

运行容器将输出:

Hello, xxx

CMD 和 ENTRYPOINT 推荐使用 Exec 格式,指令可读性更强,更容易理解。RUN 则两种格式都可以。

 

RUN

  RUN 指令通常用于安装应用和软件包。

  RUN 在当前镜像的顶部执行命令,并通过创建新的镜像层。Dockerfile 中常常包含多个 RUN 指令。

  RUN 有两种格式:

  1. Shell 格式:RUN
  2. Exec 格式:RUN ["executable", "param1", "param2"]

可以使用 RUN 安装多个包:

RUN apt-get update && apt-get install -y \  
 bzr \
 cvs \
 git \
 mercurial \
 subversion

注意:apt-get update 和 apt-get install 被放在一个 RUN 指令中执行,这样能够保证每次安装的是最新的包。如果 apt-get install 在单独的 RUN 中执行,则会使用 apt-get update 创建的镜像层,而这一层可能是很久以前缓存的。

 

CMD

CMD 指令允许用户指定容器的默认执行的命令。此命令会在容器启动且 docker run 没有指定其他命令时运行。

  • 如果 docker run 指定了其他命令,CMD 指定的默认命令将被忽略。
  • 如果 Dockerfile 中有多个 CMD 指令,只有最后一个 CMD 有效。

CMD 有三种格式:

  1. Exec 格式(推荐):CMD ["executable","param1","param2"]
  2. CMD ["param1","param2"] 为 ENTRYPOINT 提供额外的参数,此时 ENTRYPOINT 必须使用 Exec 格式。
  3. Shell 格式:CMD command param1 param2

 

举个栗子:

 1 root@ubuntu:~/0108# cat Dockerfile 
 2 FROM ubuntu
 3 CMD echo "hello world"
 4 root@ubuntu:~/0108# 
 5 root@ubuntu:~/0108# docker build -t cmd-eg-v1 .
 6 Sending build context to Docker daemon  2.048kB
 7 Step 1/2 : FROM ubuntu
 8  ---> 1d9c17228a9e
 9 Step 2/2 : CMD echo "hello world"
10  ---> Running in 73a418109975
11 Removing intermediate container 73a418109975
12  ---> 44b793b3959c
13 Successfully built 44b793b3959c
14 Successfully tagged cmd-eg-v1:latest
15 root@ubuntu:~/0108# 
16 root@ubuntu:~/0108# docker run -it cmd-eg-v1
17 hello world
18 root@ubuntu:~/0108# docker run -it cmd-eg-v1 /bin/bash
19 root@57afa1edf189:/# 

 

在执行 docker run -it [image] /bin/bash,CMD 会被忽略掉,命令 bash 被执行。

 

ENTRYPOINT

ENTRYPOINT 指令可让容器以应用程序或者服务的形式运行。

ENTRYPOINT 看上去与 CMD 很像,它们都可以指定要执行的命令及其参数。区别在于 ENTRYPOINT 不会被忽略,一定会被执行,即使运行 docker run 时指定了其他命令。

ENTRYPOINT 有两种格式:

  1. Exec 格式(推荐):ENTRYPOINT ["executable", "param1", "param2"] 
  2. Shell 格式:ENTRYPOINT command param1 param2

在为 ENTRYPOINT 选择格式时必须小心,因为这两种格式的效果差别很大。

 

Exec 格式

ENTRYPOINT 的 Exec 格式用于设置要执行的命令及其参数,同时可通过 CMD 提供额外的参数。

ENTRYPOINT 中的参数始终会被使用,而 CMD 的额外参数可以在容器启动时动态替换掉。

举个例子:

 

 1 root@ubuntu:~/0108# cat Dockerfile 
 2 FROM ubuntu
 3 ENTRYPOINT ["/bin/echo", "Hello"]
 4 CMD ["world"]
 5 root@ubuntu:~/0108# 
 6 root@ubuntu:~/0108# docker build -t cmd-eg-v2 .
 7 Sending build context to Docker daemon  2.048kB
 8 Step 1/3 : FROM ubuntu
 9  ---> 1d9c17228a9e
10 Step 2/3 : ENTRYPOINT ["/bin/echo", "Hello"]
11  ---> Running in fae6feb9277a
12 Removing intermediate container fae6feb9277a
13  ---> 93c655c722d2
14 Step 3/3 : CMD ["world"]
15  ---> Running in 0de0893f9c13
16 Removing intermediate container 0de0893f9c13
17  ---> 3632ca1d41fa
18 Successfully built 3632ca1d41fa
19 Successfully tagged cmd-eg-v2:latest
20 root@ubuntu:~/0108# 
21 root@ubuntu:~/0108# docker run -it cmd-eg-v2
22 Hello world
23 root@ubuntu:~/0108# docker run -it cmd-eg-v2 xxx
24 Hello xxx
25 root@ubuntu:~/0108# 

 

 

 

 

Shell 格式

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

小结

  1. 使用 RUN 指令安装应用和软件包,构建镜像。
  2. 如果 Docker 镜像的用途是运行应用程序或服务,比如运行一个 MySQL,应该优先使用 Exec 格式的 ENTRYPOINT 指令。CMD 可为 ENTRYPOINT 提供额外的默认参数,同时可利用 docker run 命令行替换默认参数。
  3. 如果想为容器设置默认的启动命令,可使用 CMD 指令。用户可在 docker run 命令行中替换此默认命令。

 

---------------------------引用来自-----------------------------------

https://mp.weixin.qq.com/s?__biz=MzIwMTM5MjUwMg==&mid=2653587614&idx=1&sn=2070e193da6b71861052e393eccae055&chksm=8d308087ba4709915514e06e73bba8a93fca5510f910552a8290e9a1b4ae111d7a3fd230c0a5&scene=21#wechat_redirect

posted @ 2019-01-08 13:26  gsophy  阅读(266)  评论(0编辑  收藏  举报