Dockerfile中CMD主要目的是为容器提供默认启动命令

CMD命令格式:

1、CMD ["executable","param1","param2"]

exec形式,推荐使用    exec表单被解析为JSON数组,必须使用双引号

2、CMD ["param1","param2"] 

作为entrypoint参数使用    应使用JSON数组格式

3、CMD command param1 param2 

shell形式


以nginx镜像为例

shell形式:CMD nginx "-g daemon off;"

exec形式:CMD ["nginx","-g","daemon off;"]

可以看出两种形式容器启动命令是不同的

image.png

查看容器进程,shell形式下nginx进程并不是PID为1的进程

CMD、ENTRYPOINT_第1张图片


使用shell形式命令将被解析为/bin/sh -c ,这将导致不能作为容器PID为1的进程运行,不利于docker stop时容器的优雅退出

PID1进程对于操作系统而言具有特殊意义。操作系统的PID1进程是init进程,以守护进程方式运行,是所有其他进程的祖先,具有完整的进程生命周期管理能力。在Docker容器中,PID1进程是启动进程,它也会负责容器内部进程管理的工作。而这也将导致进程管理在Docker容器内部和完整操作系统上的不同。

当执行docker stop命令时,docker会首先向容器的PID1进程发送一个SIGTERM信号,用于容器内程序的退出。如果容器在收到SIGTERM后没有结束, 那么Docker Daemon会在等待一段时间(默认是10s)后,再向容器发送SIGKILL信号,将容器杀死变为退出状态。这种方式给Docker应用提供了一个优雅的退出(graceful stop)机制,允许应用在收到stop命令时清理和释放使用中的资源。而docker kill可以向容器内PID1进程发送任何信号,缺省是发送SIGKILL信号来强制退出应用。


执行docker stop来看一下二者的区别,可以很明显看出shell形式是被强制杀死

CMD、ENTRYPOINT_第2张图片


ENTRYPOINT有两种形式:

  • ENTRYPOINT ["executable", "param1", "param2"] 

  • ENTRYPOINT command param1 param2 

ENTRYPOINT也分为shell形式跟exec形式,效果跟CMD相同,此处不做过多介绍



参考:

https://www.cnblogs.com/ilinuxer/p/6188303.html

https://docs.docker.com/engine/reference/builder/#cmd

https://docs.docker.com/engine/reference/builder/#entrypoint