Dockerfile中CMD和ENTRYPOINT探究

CMD

引用自Docker的官方文档:

The CMD instruction has three forms:
#CMD指令有如下三种形式:

CMD ["executable","param1","param2"] (exec form, this is the preferred form)
CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
CMD command param1 param2 (shell form)

There can only be one CMD instruction in a Dockerfile.
If you list more than one CMD then only the last CMD will take effect.
#一个Dockfile中只有一个CMD指令是真正有效的,如果Dockerfile中有多个CMD指令,那么只有最后一个CMD会生效。

The main purpose of a CMD is to provide defaults for an executing container. 
These defaults can include an executable, or they can omit the executable, 
in which case you must specify an ENTRYPOINT instruction as well.
#CMD指令的主要作用是给容器提供一个默认参数,这些默认参数可以是一个可执行体,
#如果你的Dockerfile中有ENTRYPOINT,那么也可以不需要执行体。

我们编写一个简单的脚本,脚本的功能是打印命令行中输入的参数,如下:
entrypoint.sh

#!/bin/bash

echo ${1}

接下来我们创建一个Dockerfile用来生成镜像:这个镜像很简单,就是拷贝一份entrypoint.sh脚本到镜像的根目录中,然后执行entrypoint.sh这个脚本,参数是"_VAR_ARGS_"

#Dockerfile_CMD
FROM centos

COPY entrypoint.sh /entrypoint.sh
RUN ["chmod", "+x", "/entrypoint.sh"]

CMD ["/bin/bash", "/entrypoint.sh", "__VAR_ARGS__"]

接下来,我们执行以下命令,来查看官方文档中对CMD的“默认”这个描述的效果:

[root@172 build] docker build -f Dockerfile_CMD -t a .
[root@172 build] docker run --rm a
__VAR_ARGS__
[root@172 build] docker run --rm a /entrypoint.sh aloha,world
aloha,world

很明显的结果,我们发现如果在docker run命令中带上启动参数的时候(/entrypoint.sh aloha,world),镜像中原始的CMD命令失效,转而执行我们的启动参数,符合官方的解读。这一点其实也就是说,CMD指令可以被覆盖。

ENTRYPOINT

引用自Docker的官方文档:

ENTRYPOINT has two forms:
#ENTRYPOINT有如下两种形式:
ENTRYPOINT ["executable", "param1", "param2"] (exec form, preferred)
ENTRYPOINT command param1 param2 (shell form)
An ENTRYPOINT allows you to configure a container that will run as an executable.
#ENTRYPOINT 指令允许你配置你的容器作为一个可执行容器

Understand how CMD and ENTRYPOINT interact
Both CMD and ENTRYPOINT instructions define what command gets executed when running a container. 
There are few rules that describe their co-operation.
#CMD和ENTRYPOINT指令都可以用来定义运行容器时所使用的命令
Dockerfile should specify at least one of CMD or ENTRYPOINT commands.
#Dockerfile至少提供一个CMD或者ENTRYPOINT指令
- ENTRYPOINT should be defined when using the container as an executable.
#当容器是一个可执行容器时,ENTRYPOINT指令必须要指定
- CMD should be used as a way of defining default arguments for an ENTRYPOINT command
or for executing an ad-hoc command in a container.
#CMD指令的内容将成为ENTRYPOINT指令的默认参数
- CMD will be overridden when running the container with alternative arguments.
#命令行提供额外参数的时候,CMD命令会被覆盖

从内容来看,ENTRYPOINT更加“硬核”,并且是可以覆盖掉CMD,让CMD退化成为ENTRYPOINT的执行参数,我们编写一个Dockerfile来验证一下:
Dockerfile_CMD_ENTRYPOINT

FROM centos

COPY entrypoint.sh /entrypoint.sh
RUN ["chmod", "+x", "/entrypoint.sh"]

CMD ["/bin/bash", "/entrypoint.sh", "__VAR_ARGS__"]
ENTRYPOINT ["/bin/bash", "/entrypoint.sh"]

运行这个镜像,我们可以看到的输出的结果是打印了/bin/bash,也就是CMD命令不生效,其第一个参数被当作ENTRYPOINT的输入参数。

[root@172 build] docker build -f Dockerfile_CMD_ENTRYPOINT -t b .
[root@172 build] docker run --rm b
/bin/bash

你可能感兴趣的:(Dockerfile中CMD和ENTRYPOINT探究)