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;"]
可以看出两种形式容器启动命令是不同的
查看容器进程,shell形式下nginx进程并不是PID为1的进程
使用shell形式命令将被解析为/bin/sh -c <command>,这将导致<command>不能作为容器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形式是被强制杀死
ENTRYPOINT有两种形式:
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2
ENTRYPOINT也分为shell形式跟exec形式,效果跟CMD相同,此处不做过多介绍
参考: