ENTRYPOINT和CMD都是让用户指定一个可执行程序, 这个可执行程序在container启动后自动启动

执行运行一个没有调用ENTRYPOINT或者CMD的docker镜像, 一定返回错误

1
2
$ docker run alpine
FATA[0000] Error response from daemon: No command specified

覆盖

首先两者都可以执行命令覆盖, 覆盖的情况如下

  • 在写Dockerfile时, ENTRYPOINT或者CMD命令会自动覆盖基础镜像的ENTRYPOINT或者CMD命令.

  • 在docker镜像运行时, 用户也可以在命令指定具体命令, 覆盖在Dockerfile里的命令.

CMD: CMD命令可以直接接命令进行覆盖

ENTRYPOINT: 使用--entrypoint参数覆盖默认的ENTRYPOINT

因为CMD命令很容易被docker run命令的方式覆盖, 所以, 如果你希望你的docker镜像的功能足够灵活, 建议在Dockerfile里调用CMD命令

执行命令的两种方法

shell表示法:

1
CMD executable  param1 param2

问题:

使用shell法run容器的时候会发现实际运行命令是/bin/sh -c

1
2
3
$ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED
15bfcddb4312 demo:latest "/bin/sh -c 'ping localhost'" 2 seconds ago

如果一个镜像甚至连shell程序(/bin/sh)都没有.那docker容器就不能运行.

而反观exec法则没有这个问题

exec表示法:

1
CMD ["executable","param1","param2"] 

无论用的是ENTRYPOINT还是CMD命令, 都强烈建议采用exec表示法

两个表示法的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Dockerfile    Command

ENTRYPOINT /bin/ping -c 3
CMD localhost /bin/sh -c '/bin/ping -c 3' /bin/sh -c localhost


ENTRYPOINT ["/bin/ping","-c","3"]
CMD localhost /bin/ping -c 3 /bin/sh -c localhost

ENTRYPOINT /bin/ping -c 3
CMD ["localhost"]" /bin/sh -c '/bin/ping -c 3' localhost

ENTRYPOINT ["/bin/ping","-c","3"]
CMD ["localhost"] /bin/ping -c 3 localhost

ENTRYPOINT 和 CMD组合使用

一般场景的使用如下

组合使用ENTRYPOINT和CMD, ENTRYPOINT指定默认的运行命令, CMD指定默认的运行参数.

dockerfile例子

1
2
3
FROM ubuntu:trusty
ENTRYPOINT ["/bin/ping","-c","3"]
CMD ["localhost"]

执行的命令是ENTRYPOINT和CMD指令拼接而成. ENTRYPOINT和CMD同时存在时, docker把CMD的命令拼接到ENTRYPOINT命令之后, 拼接后的命令才是最终执行的命令

注意到参数-c 3, 这个参数表示ping请求只发送3次, 这个参数包括在ENTRYPOINT里面, 相当于硬编码docker镜像中. 每次执行docker镜像都会带上这个参数, 并且也不能被CMD参数覆盖.