CMD 与 ENTRYPOINT 的差异
两者都会用到
在 Dockerfile 中,Entrypoint 和 CMD 都会在 docker run 的时候被用到。具体的被用的方式是:Entrypoint CMD
。
也就是说如果你同时指定了 Entrypoint 和 CMD,那么 Docker 就会将 Entrypoint 的内容作为主体,然后后面附加 CMD 的内容,例如这么一段:
那么当你执行 docker run test
的时候,实际上 docker 运行的进程就会是:
/bin/sh -c "cat /etc/passwd"
ENTRYPOINT 有默认值
- 不主动指定 Dockerfile 中的 Entrypoint,docker 默认就会使用 /bin/sh -c。
- 但是 CMD 的没有默认值,也就是说如果你不主动填写 CMD,那么就没有 CMD 的值;
CMD 可以被替换
ENTRYPOINT 和 CMD 的差异之二:ENTRYPOINT 不会被运行时替换,也不能被运行时替换,但是 CMD 会。CMD 中的参数不一定执行。CMD 可以是纯参数模式
链接:https://stackoverflow.com/questions/21553353/what-is-the-difference-between-cmd-and-entrypoint-in-a-dockerfileThe
ENTRYPOINT
is the program that will be run, and the value passed to the container will be appended to it. The >ENTRYPOINT
can be overridden by specifying an >--entrypoint
flag, followed by the new entry point you want to use.ENTRYPOINT
是程序将要执行的命令,从 container 传入的值会添加到 ENTRYPOINT 后面。ENTRYPOINT
会被--entrypoint
flag 覆盖。sleep 10 秒的镜像
创建一个启动时休眠 10 秒的镜像:
FROM ubuntu
CMD sleep 10
build 并 启动镜像:
docker build -t custom_sleep .
docker run custom_sleep
# sleeps for 10 seconds and exits
休眠 N 秒的镜像
使用
ENTRYPOINT
达到休眠 N 秒的目的:FROM ubuntu
ENTRYPOINT sleep
启动:
docker run custom_sleep 20
休眠 N 秒的镜像增加默认值
What about a default value? Well, you guessed it right:
FROM ubuntu
ENTRYPOINT ["sleep"]
CMD ["10"]
不同参数模式
注:此部分没看懂。
CMD ["executable", "param1", "param2"]
CMD command param1 param2
那么既然有两种方式,那么肯定是有所差异的,他们之间的差异又是什么呢?首先在执行方式层面,他们就不一样,第一种 exec 模式,hi 被 docker 使用 fork-exec 的方式执行,这是推荐的方式,这样做的好处有:xxx;而第二种,会被放在 /bin/sh 中执行,好处是支持用户交互。如果从系统层面来看,通过 exec 方式运行,那么将不会关注到 Dockerfile 中执行的环境变量等,而通过 shell 方式运行的却是可以使用到 ENV 设置的环境变量;还有一个差别就是通过 exec 模型运行,那么进程在 Docker 中的 PID 就是 1,可以收到 docker 外部触发的系统信号;而通过 shell 运行的进程则收不到系统进程。
所以这里就存在一定的问题,因为有的时候我们的应用不能简单直白得就通过一个 exec 模式直接运行在 Docker 中,可能还需要处理一些环境相关的设置或者错误处理和故障恢复之类的,但是又系统能够很好得接受和处理系统信号,为了兼顾 exec 和 shell 两种模式的优点,一个被广泛使用的最佳实践就是通过一个entrypoint.sh
的脚本作为 ENTRYPOINT,然后再entrypoint.sh
中运行期望中的程序以及做信号处理等事情,这样就兼顾到了程序和环境的友好。例如这一个 postgres 的 Dockerfile 就是采用这种方式,而且他的entrypoint.sh
也不复杂,有兴趣可以看一下:postgres entrypoint.sh