前言

  Entrypoint的作用是,把整个container变成了一个可执行的文件,这样不能够通过替换CMD的方法来改变创建container的方式。但是可以通过参数传递的方法影响到container内部。


一、ENTRYPOINT 命令格式介绍

ENTRYPOINT 有两种格式:

  • ENTRYPOINT [“executable”, “param1”, “param2”] (exec 格式,首选)
  • ENTRYPOINT command param1 param2 (shell 格式)

exec 格式
  docker run image 后面跟的命令行参数将会添加到 ENTRYPOINT 所有参数的最后,且会覆盖掉所有 CMD 命令中的参数。这将允许运行时传递参数给 ENTRYPOINT 命令,例如 docker run image -d 会将 -d 参数传给 ENTRYPOINT 命令 。ENTRYPOINT 命令可以通过 docker run --entrypoint 参数来覆盖 。

shell 格式
  会忽略所有 CMD 命令的参数和 docker run 的命令行参数,ENTRYPOINT 要运行的命令会作为 /bin/sh -c 的子命令运行,而且 /bin/sh 不会传递信号,也就是说 ENTRYPOINT 要运行的命令不是 PID 为 1 的进程,且不会收到 Unix 信号,所以你要执行的命令不会收到 docker stop 发出的 SIGTERM 信号。

二、示例

Exec格式
  用使用CMD的参数,run [image] 会替代CMD参数,会使用run中的多个参数

示例一
ENTRYPOINT ["/bin/echo", "Hello"]
CMD ["world"] //表示默认参数,没提供参数,则使用此参数

docker run -it [image] 输出:Hello world 
docker run -it [image] "hanke"  输出 Hello hanke  ,不使用默认参数
docker run -it [image] "hanke" "hujing"  输出 Hello hankd hujing ,使用多个提供参数

示例二
可以使用 exec 格式的 ENTRYPOINT 来设置稳定的默认命令和参数,再通过CMD 命令设置容易变动的默认值。

FROM ubuntu
ENTRYPOINT["top","-b"]
CMD["-c"]

运行这个容器,可以看到只有 top 一个进程:

$ docker run -it --rm --name testtop -H
top - 08:25:00 up  7:27,  0users,  load average: 0.00, 0.01, 0.05
Threads:   1total,   1running,   0sleeping,   0stopped,   0zombie
%Cpu(s):  0.1 us,  0.1 sy,  0.0 ni, 99.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem:   2056668total,  1616832used,   439836free,    99352buffers
KiB Swap:  1441840total,        0used,  1441840free.  1324440cached Mem
PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
    1root      2001974423362080R  0.0  0.1   0:00.04 top

可以通过 docker exec 进一步确认:

$ docker exec-it testps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         12.6  0.1  197522352?        Ss+  08:24   0:00 top -b -H
root         70.0  0.1  155722164?        R+   08:25   0:00 ps aux

Shell格式
  可以给 ENTRYPOINT 命令指定一个纯字符串,它将通过 /bin/sh -c 执行。这种格式会处理 shell 环境变量,忽略所有的 CMD 命令和 docker run 命令行参数。为了确保 docker stop 能正确的停止运行的 ENTRYPOINT 命令,容器需要通过 exec 来启动。

FROM ubuntu
ENTRYPOINT exec top -b

运行这个镜像,将会看到 PID 为 1 的进程:

	$ docker run -it --rm --name test top
	Mem: 1704520K used, 352148K free, 0K shrd, 0K buff, 140368121167873K cached
	CPU:   5% usr   0% sys   0% nic  94% idle   0% io   0% irq   0% sirq
	Load average: 0.08 0.03 0.05 2/98 6
	  PID  PPID USER     STAT   VSZ %VSZ %CPU COMMAND
	    1     0 root     R     3164   0%   0% top -b

如果忘了在 ENTRYPOINT 命令中添加 exec:

FROM ubuntu
ENTRYPOINT top  -b
CMD  --ignored-param1

运行

	$ docker run -it --name test top --ignored-param2
	Mem: 1704184K used, 352484K free, 0K shrd, 0K buff, 140621524238337K cached
	CPU:   9% usr   2% sys   0% nic  88% idle   0% io   0% irq   0% sirq
	Load average: 0.01 0.02 0.05 2/101 7
	  PID  PPID USER     STAT   VSZ %VSZ %CPU COMMAND
	    1     0 root     S     3168   0%   0% /bin/sh -c top -b cmd cmd2
	    7     1 root     R     3164   0%   0% top -b
从 top 的输出中可以看到 PID 为 1 的进程不是 ENTRYPOINT 中设置的命令
这时运行 docker stop test,容器不能优雅的退出(docker stop 命令在一个超时时间后会强制发送 SIGKILL[9] 信号):
	$ docker exec -it test ps aux
	PID   USER     COMMAND
	    1 root     /bin/sh -c top -b cmd cmd2
	    7 root     top -b
	    8 root     ps aux
	$ /usr/bin/time docker stop test
	test
	real	0m 10.19s
	user	0m 0.04s
	sys	0m 0.03s

总结

CMD 和 ENTRYPOINT 命令都定义了容器运行时运行命令。下面有几条规则:

  • Dockerfile 必须有一条 CMD 或 ENTRYPOINT 命令
  • 如果容器作为可执行程序运行,需要指定 ENTRYPOINT 命令,
  • CMD 命令应该用来定义 ENTRYPOINT 命令的默认参数

下表展示了 ENTRYPOINT / CMD 组合:
在这里插入图片描述

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐