dockerfile 中的 entrypoint 和 cmd

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 后面的所有参数会被追加到 ENTRYPOINT exec form 后,并且会覆盖CMD 指定的值。 这可以传递参数给entrypoint。例如:docker run -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 的 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的默认参数来使用

两者的关系图如下:


dockerfile 中的 entrypoint 和 cmd_第1张图片
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等信号是没有反应的

参考
  • exec, sh 和souce 三者的区别
  • entrypoint-vs-cmd

你可能感兴趣的:(dockerfile 中的 entrypoint 和 cmd)