详文:理解Docker容器的进程管理:https://yq.aliyun.com/articles/5545
在Docker中,每个Container都是Docker Daemon的子进程。
docker exec
命令可以进入指定的容器内部执行命令。由它启动的进程属于容器的namespace和相应的cgroup。但是这些进程的父进程是Docker Daemon而非容器的PID1进程。
如果我们在宿主机操作系统中手动杀掉容器的启动进程,容器会自动结束,而容器名空间中所有进程也会退出。
Docker提供了两个命令docker stop
和docker kill
来向容器中的PID1进程发送信号。
当执行docker stop
命令时,docker会首先向容器的PID1进程发送一个SIGTERM信号,用于容器内程序的退出。如果容器在收到SIGTERM后没有结束, 那么Docker Daemon会在等待一段时间(默认是10s)后,再向容器发送SIGKILL信号,将容器杀死变为退出状态。这种方式给Docker应用提供了一个优雅的退出(graceful stop)机制,允许应用在收到stop命令时清理和释放使用中的资源。而docker kill
可以向容器内PID1进程发送任何信号,缺省是发送SIGKILL信号来强制退出应用。
- 容器的PID1进程需要能够正确的处理SIGTERM信号来支持优雅退出。
- 如果容器中包含多个进程,需要PID1进程能够正确的传播SIGTERM信号来结束所有的子进程之后再退出。
- 确保PID1进程是期望的进程。缺省sh/bash进程没有提供SIGTERM的处理,需要通过shell脚本来设置正确的PID1进程,或捕获SIGTERM信号。
在docker容器中,PID1同样会接管孤儿进程。
如果在容器中运行多个进程,PID1进程需要有能力接管“孤儿”进程并回收“僵尸”进程。
利用Supervisor等工具作为PID1进程是在容器中支持多进程管理的主要实现方式;和简单利用shell脚本fork子进程相比,采用Supervisor等工具有很多好处:
- 一些传统的服务不能以PID1进程的方式执行,利用Supervisor可以方便的适配
- Supervisor这些监控工具大多提供了对SIGTERM的信号传播支持,可以支持子进程优雅的退出