如果容器中的进程没有收到 SIGTERM
信号,很有可能是因为应用进程不是 PID 1
,PID 1 是 shell
,而应用进程只是 shell
的子进程。而 shell 不具备 init
系统的功能,也就不会将操作系统的信号转发到子进程上,这也是容器中的应用没有收到 SIGTERM
信号的常见原因。
问题的根源就来自 Dockerfile
,例如:
FROM alpine:3.7 COPY popcorn.sh . RUN chmod +x popcorn.sh ENTRYPOINT ./popcorn.sh
ENTRYPOINT
指令使用的是 shell 模式,这样 Docker 就会把应用放到 shell
中运行,因此 shell
是 PID 1。
解决方案有以下几种:
与其使用 shell 模式,不如使用 exec 模式,例如:
FROM alpine:3.7 COPY popcorn.sh . RUN chmod +x popcorn.sh ENTRYPOINT ["./popcorn.sh"]
这样 PID 1 就是 ./popcorn.sh
,它将负责响应所有发送到容器的信号,至于 ./popcorn.sh
是否真的能捕捉到系统信号,那是另一回事。
举个例子,假设使用上面的 Dockerfile 来构建镜像,popcorn.sh
脚本每过一秒打印一次日期:
#!/bin/sh while true do date sleep 1 done
构建镜像并创建容器: