首先说明下RUN、CMD、ENTRYPOINT 等命令都可以用来执行命令,但是各有不同的特点
- RUN 在Build Image的时候执行。
- CMD ENTRYPOINT 在运行Image时执行。
- CMD 可以和ENTRYPOINT 搭配使用,也可以单个命令使用。当CMD 和ENTRYPOINT都出现在一个DockerFile中时,CMD中设置的信息(EXEC格式的)都以参数的形式提供给ENTRYPOINT命令。EntryPoint 命令没有设置时,默认是/bin/bash
- ENTRYPOINT的命令不可以简单被覆盖,但可以使用run 中的--entrypoint被覆盖,如果docker run时提供参数,这些参数附加在ENTRYPOINT 里面设置的内容后面。
- 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 ,不提供任何参数
然后我们提供参数的情况下:
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