ENTRYPOINT 指令
ENTRYPOINT 指令可以有两种写法:
- ENTRYPOINT ["executable", "param1", "param2"] 【exec form, 推荐使用写法】
- ENTRYPOINT command param1 param2 【shell form, 等同于execform 的 ENTRYPOINT ["sh", "-c, "command param1 param2"]】
CMD 指令
CMD 指令有三种形式:
- CMD ["executable","param1","param2"] (exec form, 推荐形式)
- CMD ["param1","param2"] (给 ENTRYPOINT 指令提供默认参数)
- CMD command param1 param2 (shell form,基本同 ENTRYPOINT的参数)
exec form 和 shell form 隐含规则
-
exec form
会被docker engine解析为一个 JSON 数组, 所以必须使用双引号,不能使用单引号 - 可以使用
docker run --entrypoint
覆盖ENTRYPOINT
指令 -
docker run <image>
后面的所有参数会被追加到ENTRYPOINT exec form
后,并且会覆盖CMD
指定的值。 这可以传递参数给entrypoint。例如:docker run <image> -d
将会把 -d 参数传递给 entry point。
例如:
ENTRYPOINT [nginx]
CMD ['-g', 'daemon off;']
运行 docker run -i -t --rm -p 80:80 nginx
, 会执行 nginx -g "daemon off"
运行 docker run -i -t --rm -p 80:80 nginx nginx -t
, 则执行 nginx -t
-
ENTRYPOINT shell form
将会阻止所有的 CMD指令参数 和 run命令行参数被使用,但是它以/bin/sh -c
子命令的形式执行, 不能接收 signals,这意味着执行文件并不是以 container的 pid来运行命令,所以不能接到docker stop <container>
的 SIGTERM -
exec form
不能调用shell 命令
ENTRYPOINT [ "echo", "$HOME" ] ## 不会解析 $HOME 变量
ENTRYPOINT [ "sh", "-c", "echo $HOME" ] ## 会解携 $HOME 变量
- 一个dockerfile只能有一个cmd起作用,如果有多个,则使用最后一个, 升级Dockerfile 会被置空,因此,每个Dockerfile 必须定义自己的 CMD 指令
ENTRYPOINT 和 CMD 的配合使用形式
- ENTRYPOINT 和 CMD 至少包含一个
- 当使用容器当作可执行文件是应当定义 ENTRYPOINT
- CMD 主要被作为提供ENTRYPOINT的默认参数来使用
两者的关系图如下:
entrypoint-vs-cmd
shell 中 source,sh,和exec的区别
shell form不推荐的原因在于不能接收signal信号, 再深究其原因,在于 shell三种执行命令方式的不同
shell 执行脚本或命令有三种:
- sh 默认
使用$ sh script.sh执行脚本时,当前shell是父进程,生成一个子shell进程,在子shell中执行脚本。脚本执行完毕,退出子shell,回到当前shell。
sh script.sh
- source
使用$ source script.sh方式,在当前上下文中执行脚本,不会生成新的进程。脚本执行完毕,回到当前shell。
source script.sh
- exec
exec command
使用exec command方式,会用command进程替换当前shell进程,并且保持PID不变。执行完毕,直接退出,不回到之前的shell环境。
以上几种形式的不同点在于 :
- souce,在subshell执行,后返回父shell, 会改变当前的执行环境
- sh, 在subshell执行,后返回父shell, 当前执行环境不会改变
- exec, 在父shell中直接执行, 执行完会调用exit,退出当前进程
subshell 对signal等信号是没有反应的