首先说明下RUN、CMD、ENTRYPOINT 等命令都可以用来执行命令,但是各有不同的特点

  1. RUN 在Build Image的时候执行。
  2. CMD ENTRYPOINT 在运行Image时执行。
  3. CMD 可以和ENTRYPOINT 搭配使用,也可以单个命令使用。当CMD 和ENTRYPOINT都出现在一个DockerFile中时,CMD中设置的信息(EXEC格式的)都以参数的形式提供给ENTRYPOINT命令。EntryPoint 命令没有设置时,默认是/bin/bash
  4. ENTRYPOINT的命令不可以简单被覆盖,但可以使用run 中的--entrypoint被覆盖,如果docker run时提供参数,这些参数附加在ENTRYPOINT 里面设置的内容后面。
  5. CMD 单独使用时,如果run 命令后面中提供参数,那么参数会完全覆盖CMD

来看一个例子可以很好的说明以上情况,我们的大概步骤是创建一个简单的Docker Image ,使用Echo命令来看CMD命令和ENTRYPOINT命令在单独使用、组合使用等情况下的区别。

  • 第一次我们的Dockerfile 如下,我只使用CMD命令

FROM centos

MAINTAINER [email protected]

CMD ["/bin/dir","/bin"]

chef@chef:~/dockerfiles/cmd_entrypoint$ docker build -t echotest:cmd -f Dockerfile_cmd .

Sending build context to Docker daemon 4.096 kB

Step 1 : FROM centos

---> 87e5b6b3ccc1

Step 2 : MAINTAINER [email protected]

---> Using cache

---> a9bea6e7d663

Step 3 : CMD /bin/dir /bin

---> Running in abc9360528ee

---> 07103bc09e6f

Removing intermediate container abc9360528ee

Successfully built 07103bc09e6f

然后我们执行run ,不提供任何参数

Dockerfile中CMD命令和ENTRYPOINT 命令的说明_第1张图片

然后我们提供参数的情况下:

chef@chef:~/dockerfiles/cmd_entrypoint$ docker run --rm -it echotest:cmd /bin/echo

# 以上命令没有任何输出,正常情况下应该是下面输出(因为我们CMD命令中提供的是/bin/dir命令:

chef@chef:~/dockerfiles/cmd_entrypoint$ dir /bin/echo

/bin/echo

# 我接着执行下面命令,发现我们提供的参数完全替换了CMD中的所有命令(/bin/dir /bin 被/bin/echo test 完全替换了,验证了前面总结的第5点)

chef@chef:~/dockerfiles/cmd_entrypoint$ docker run --rm -it echotest:cmd /bin/echo test

test

  • 第二个测试,我们的Dockerfile内容如下,我们测试仅使用Entrypoint的情况。

chef@chef:~/dockerfiles/cmd_entrypoint$ cat Dockerfile_entrypoint

FROM centos

MAINTAINER [email protected]

ENTRYPOINT ["/bin/echo","defaultParam"]

#CMD ["/bin/dir","/bin"]

# 然后我们Build 另外一个image echotest:entrypoint

chef@chef:~/dockerfiles/cmd_entrypoint$ docker build -t echotest:entrypoint -f Dockerfile_entrypoint .

Sending build context to Docker daemon 4.096 kB

Step 1 : FROM centos

---> 87e5b6b3ccc1

Step 2 : MAINTAINER [email protected]

---> Using cache

---> a9bea6e7d663

Step 3 : ENTRYPOINT /bin/echo defaultParam

---> Running in f17009dd0dc1

---> 9f7dab52dc3a

Removing intermediate container f17009dd0dc1

Successfully built 9f7dab52dc3a

# 以默认参数执行

chef@chef:~/dockerfiles/cmd_entrypoint$ docker run --rm -it echotest:entrypoint

defaultParam

# 提供参数情况下,我们发现param1 并不像CMD一样,CMD是拿docker run 提供的参数完全覆盖CMD内容,而ENTRYPOINT是把参数附加到ENTRYPOINT内容后面。

chef@chef:~/dockerfiles/cmd_entrypoint$ docker run --rm -it echotest:entrypoint param1

defaultParam param1

# 如果想替换 ENTRYPONT 的内容,可以使用docker run --entrypointdocker

chef@chef:~/dockerfiles/cmd_entrypoint$ docker run --rm -it --entrypoint /bin/ping echotest:entrypoint param1

ping: unknown host param1

chef@chef:~/dockerfiles/cmd_entrypoint$ docker run --rm -it --entrypoint /bin/ping echotest:entrypoint localhost

PING localhost (127.0.0.1) 56(84) bytes of data.

64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.051 ms

64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.128 ms

64 bytes from localhost (127.0.0.1): icmp_seq=3 ttl=64 time=0.058 ms

64 bytes from localhost (127.0.0.1): icmp_seq=4 ttl=64 time=0.068 ms

^C

--- localhost ping statistics ---

4 packets transmitted, 4 received, 0% packet loss, time 2997ms

rtt min/avg/max/mdev = 0.051/0.076/0.128/0.031 ms

[root@learndocker vagrant]# docker run --rm --entrypoint "/bin/bash" echotest:entrypoint -c "ping www.bing.com"

PING cn.a-0001.a-msedge.net (202.89.233.103) 56(84) bytes of data.

64 bytes from 202.89.233.103: icmp_seq=1 ttl=115 time=37.1 ms

64 bytes from 202.89.233.103: icmp_seq=2 ttl=115 time=37.2 ms

64 bytes from 202.89.233.103: icmp_seq=3 ttl=115 time=36.9 ms

64 bytes from 202.89.233.103: icmp_seq=4 ttl=115 time=36.7 ms

  • 第三个测试,我们的Dockerfile内容如下,我们测试同时使用Entrypoint和CMD的情况。

先看Dockerfile内容,我这里故意把CMD和ENTRYPOINT中执行的命令设置成不同的

chef@chef:~/dockerfiles/cmd_entrypoint$ cat Dockerfile_cmd_and_entrypoint

FROM centos

MAINTAINER [email protected]

ENTRYPOINT ["/bin/echo","defaultParam"]

CMD ["/bin/dir","/bin"]

chef@chef:~/dockerfiles/cmd_entrypoint$ docker build -t echotest:entrypointAndCmd -f Dockerfile_cmd_and_entrypoint .

Sending build context to Docker daemon 4.096 kB

Step 1 : FROM centos

---> 87e5b6b3ccc1

Step 2 : MAINTAINER [email protected]

---> Using cache

---> a9bea6e7d663

Step 3 : ENTRYPOINT /bin/echo defaultParam

---> Using cache

---> 9f7dab52dc3a

Step 4 : CMD /bin/dir /bin

---> Running in 0bb1e042a2a0

---> 91eb9487a88a

Removing intermediate container 0bb1e042a2a0

Successfully built 91eb9487a88a

# 我这里发现当同时存在ENTRYPOINT和CMD命令时,使用默认参数执行时,会把CMD 中的内容以参数的形式提供给ENTRYPOINT 命令。等下我们看看在Dockerfile 中把ENTRYPOINT命令和CMD命令出现的顺序对调,看是否有影响。

chef@chef:~/dockerfiles/cmd_entrypoint$ docker run --rm -it echotest:entrypointAndCmd

defaultParam /bin/dir /bin

# 执行有参数的情况,CMD中的内容完全被我们在docker run 提供的参数替代了,然后以参数提供给ENTRYPOINT命令。

chef@chef:~/dockerfiles/cmd_entrypoint$ docker run --rm -it echotest:entrypointAndCmd paramCus

defaultParam paramCus

# 使用docker run --entrypoint 覆盖ENTRYPOINT内容。

chef@chef:~/dockerfiles/cmd_entrypoint$ docker run --rm -it --entrypoint /bin/ls echotest:entrypointAndCmd paramCus

/bin/ls: cannot access paramCus: No such file or directory

chef@chef:~/dockerfiles/cmd_entrypoint$ docker run --rm -it --entrypoint /bin/ls echotest:entrypointAndCmd /sbin

addgnupghome build-locale-archive cracklib-packer fsck.cramfs grpck

# 这里测试下Dockerfile中如果CMD和ENTRYPOINT命令的顺序如果和上面的颠倒,是否对结果有影响,结果是发现没有影响

chef@chef:~/dockerfiles/cmd_entrypoint$ cat Dockerfile

FROM centos

MAINTAINER [email protected]

CMD ["/bin/dir","/bin"]

ENTRYPOINT ["/bin/echo","defaultParam"]

chef@chef:~/dockerfiles/cmd_entrypoint$ docker build -t echotest .

Sending build context to Docker daemon 5.12 kB

Step 1 : FROM centos

---> 87e5b6b3ccc1

Step 2 : MAINTAINER [email protected]

---> Using cache

---> a9bea6e7d663

Step 3 : CMD /bin/dir /bin

---> Using cache

---> 07103bc09e6f

Step 4 : ENTRYPOINT /bin/echo defaultParam

---> Running in 091b72e36f4f

---> b01150245beb

Removing intermediate container 091b72e36f4f

Successfully built b01150245beb

chef@chef:~/dockerfiles/cmd_entrypoint$ docker run --rm -it echotest

defaultParam /bin/dir /bin

chef@chef:~/dockerfiles/cmd_entrypoint$ docker run --rm -it echotest paramCus

defaultParam paramCus

chef@chef:~/dockerfiles/cmd_entrypoint$ docker run --rm -it --entrypoint /bin/ls echotest paramCus

/bin/ls: cannot access paramCus: No such file or directory

chef@chef:~/dockerfiles/cmd_entrypoint$ docker run --rm -it --entrypoint /bin/ls echotest /sbin

addgnupghome build-locale-archive cracklib-packer fsck.cramfs grpck

清理现场:

chef@chef:~/dockerfiles/cmd_entrypoint$ docker images echotest*

REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE

echotest latest b01150245beb 4 minutes ago 224 MB

echotest entrypointAndCmd 91eb9487a88a 17 minutes ago 224 MB

echotest entrypoint 9f7dab52dc3a 26 minutes ago 224 MB

echotest cmd 07103bc09e6f 38 minutes ago 224 MB

chef@chef:~/dockerfiles/cmd_entrypoint$ docker rmi $(docker images -q echotest*)

Untagged: echotest:latest

Deleted: b01150245bebc9ff2c44ed259861a5466fbaf1f9bc8339a4ed965e38299e3380

Untagged: echotest:entrypointAndCmd

Deleted: 91eb9487a88a70af6e91568018b11ca52574d47ffaed8b2600f24897027252d8

Untagged: echotest:entrypoint

Deleted: 9f7dab52dc3a33693743ffc34b463f820b3e954291927d73ca09e29c43fde80a

Untagged: echotest:cmd

Deleted: 07103bc09e6f918199f4a9f34dd13f4bf1eaab8bf415d5b70e360dc6885b5f9b