Dockerfile中CMD和ENTRYPOINT的用法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dockerfile中CMD和ENTRYPOINT的用法相关的知识,希望对你有一定的参考价值。

一、 ENTRYPOINT指令

ENTRYPOINT 的两种格式:
? ENTRYPOINT ["executable", "param1", "param2"] (exec格式,推荐使用此格式)
? ENTRYPOINT command param1 param2 (shell 格式)

ENTRYPOINT 的目的和 CMD 一样,都是指定容器的启动程序及参数。ENTRYPOINT 在运行时也可以通过 docker run 的参数 --entrypoint 来替代镜像中默认的ENTRYPOINT,通过 --entrypoint 传的必须是可执行的二进制程序, 即不会以sh -c 形式执行。

当指定了 ENTRYPOINT (exec格式)后,CMD 的含义就发生了改变,不再是直接运行的命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令,换句话说实际执行时,将变为:<ENTRYPOINT> "<CMD>"

通过docker run <image>启动容器时的命令行参数将作为ENTRYPOINT的参数追加到其已有的参数后面,此时所有的CMD参数将无效,被命令行参数覆盖;

CMD作为 ENTRYPOINT 的参数时需要是exec格式,如果是shell格式将转化成/bin/sh -c 式的exec格式,作为参数传给 ENTRYPOINT 时可能会出错;

当指定了ENTRYPOINT 为shell格式, CMD将无效, 即dockerfile里的CMD和 启动容器时传的命令行参数都将无效,此时ENTRYPOINT 将以 /bin/sh –c 的形式启动,即作为sh的子命令来执行,这种形式下ENTRYPOINT的执行程序不能通过Unix 信号控制,因进程号不是容器的PID 1 (sh的进程PID为1),也就不能以docker stop <container> 的形式来优雅地停止(接收SIGTERM信号)ENTRYPOINT的执行程序 ,因为这时docker stop <container>会在超时时间后通过发送SIGKILL信号给sh 强制停止容器,这会导致stop时间加长,为避免这种缺点,在shell命令前加exec,以这种方式运行即可, 如: ENTRYPOINT exec <shell command>。
和shell格式不同,当ENTRYPOINT是exec格式时不会调用shell,通常的shell变量将不会被解析执行,ENTRYPOINT [ "echo", "$HOME" ] 中的$HOME不会被替换,如果需要变量替换,则可以用shell格式的ENTRYPOINT。

二、 CMD指令

启动容器的时候,需要指定所运行的程序及参数。CMD 指令就是用于指定默认的容器主进程的启动命令的。

CMD指令有三种格式:
? CMD ["executable","param1","param2"] (exec 格式,推荐用此格式)
? CMD ["param1","param2"] (作为ENTRYPOINT 的默认参数)
? CMD command param1 param2 (shell 格式)

在dockerfile中只能有1个CMD指令,如有多个,最后一个生效。CMD的目的是提供默认的执行程序或执行程序的参数给容器,如果是参数,需要有ENTRYPOINT提供执行程序。
如果dockerfile中同时指定了ENTRYPOINT和CMD,CMD将作为ENTRYPOINT的默认参数,这里两个指令都指的是exec 格式,都将解析为JSON数组,所以只能用双引号;

exec格式不会解析shell环境变量,如CMD [ "echo", "$HOME" ] 将无法解析变量HOME变量,dockerfile里如果CMD用shell格式,在实际执行时将以 /bin/sh -c 执行,如:
CMD echo $HOME
在实际执行时将变成CMD [ "sh", "-c", "echo $HOME" ] 也就会解析出HOME变量。
CMD用exec格式执行系统的命令时,需要命令的全路径和JSON数组格式,就是得使用双引号,每个参数单独分别地追加在数组中,如下用法:
CMD [“/usr/bin/wc”, ”--help”]

三、 理解和结合使用CMD和ENTRYPOINT

  1. Dockerfile 应该至少指定CMD或ENTRYPOINT其中的1个;
  2. 容器用作可执行的程序应用时应该用ENTRYPOINT;
  3. CMD应该用作ENTRYPOINT的默认参数来使用,或是在容器中执行临时的命令;
  4. 启动容器时如果传递参数将覆盖dockerfile中指定的CMD参数;

下表列出了在CMD和ENTRYPOINT结合使用的情况下,哪个命令最终生效:

技术分享图片

以上内容参考官方文档:
https://docs.docker.com/engine/reference/builder/#usage

以上是关于Dockerfile中CMD和ENTRYPOINT的用法的主要内容,如果未能解决你的问题,请参考以下文章

Dockerfile中CMD和ENTRYPOINT的用法

Dockerfile中ENTRYPOINT 和 CMD的区别

Dockerfile 中的 CMD 和 ENTRYPOINT 有啥区别?

Dockerfile 中的 CMD 与 ENTRYPOINT

dockerfile:如何使用基础镜像中的 CMD 或 ENTRYPOINT

Dockerfile中CMD,ENTRYPOINT及ADD,COPY的区别