摘要如果您曾经做过docker,则可能曾使用docker stop命令停止正在运行的容器。 有些人使用docker kill命令强制关闭容器,或将信号传递给容器中的进程。 这些操作的本质是通过从主机向容器发送信号来实现主机与容器中的程序的交互。
例如,可以向容器中的APP应用程序发送重新加载信号。 容器中的APP应用程序收到信号后,运行相应的处理程序以完成配置文件的重新加载工作。
介绍docker容器中信号捕获的基本知识。
http://www.Sina.com/http://www.Sina.com /
进程需要为自己感兴趣的信号注册处理程序。 例如,为了优雅地结束程序,典型的程序处理SIGTERM信号。 与SIGTERM信号不同,SIGKILL信号粗暴地结束过程。 因此,我们的APP应用程序必须捕获和处理SIGTERM信号,以实现优雅地结束程序的目录。 如果我们失败了,用户只能通过SIGKILL信号这一终极手段。 除了SIGTERM和SIGKILL之外,还有支持用户定制行为的信号,例如SIGUSR1。
以下代码简要介绍了如何在nodejs中注册信号处理程序。
信号(linux)Docker中的stop和kill命令用于向容器发送信号。信号是一种进程间通信的形式。一个信号就是内核发送给进程的一个消息,告诉进程发生了某种事件。当一个信号被发送给一个进程后,进程会立即中断当前的执行流并开始执行信号的处理程序。如果没有为这个信号指定处理程序,就执行默认的处理程序。
stop命令首先发送SIGTERM信号,等待APP描述优雅地结束。 如果发现APP没有结束(用户可以指定等待时间),则再发送一个SIGKILL信号强制结束程序。
kill命令默认发送SIGKILL信号。 当然,可以使用-s选项指定任意信号。
使用nodejs描述信号在容器中的行为。 创建具有以下内容的app.js文件:
此APP应用程序是一个http服务,它接收端口3000并注册了SIGINT和SIGTERM信号处理程序。 下面介绍了以不同的方式在容器上运行程序时对信号的处理。
创建文件33558www.Sina.com/dockerfile并将上述APP应用程序打包为镜像:
在此请注意ENTRYPOINT命令的写法。 该写入方法使node在容器中作为第一个进程运行。
接下来,创建镜像。
$ docker build-- no-cache-t signal-app-fdockerfile .然后启动容器以执行APP应用程序。
$ docker run-it-- RM-p 300033603000-- name=' my-app ' signal-app此时,node应用于容器的进程号为1。
退出程序并执行命令:
$ dockercontainerkill-- signal=' sigterm ' my-app此时,APP应用程序将按预期结束。
容器中的信号创建用于启动APP应用程序的脚本文件app1.sh。 内容如下。
然后,按如下方式创建Dockerfile1文件:
接下来,创建镜像。
$ docker build-- no-cache-t signal-app1- fdockerfile1.然后启动容器以执行APP设置。
$ docker run-it-- RM-p 300033603000-- name=' my-app1' signal-app 1此时,节点应用于容器的进程号不再是1。
这个时候试着向my-app1发送SIGTERM信号的话,就不能再结束程序了! 在这种情况下,APP应用程序由bash脚本调用,bash将SIGTERM信号作为容器中的第一个进程接收,但没有采取任何响应行为。
我们可以做以下事情
结束APP,最终向容器中的第一个进程发送了SIGKILL信号。
注意,只有容器中的 1 号进程能够收到信号,这一点非常关键!创建另一个用于启动APP应用程序的脚本文件app2.sh。 内容如下。
#!/usr/bin/envbashset-xpid=0# SIG usr1- handler my _ handler () echo ' my _ handler ' } # sigterm-handler term _ () then kill-sigterm ' $ PID ' wait ' $ PID ' fi exit 143; # 12815-- sigterm } # setup handlers # on callback,kill the last background process,which is ` tail-f/dev/null ` andexecull ` my_handler' SIGUSR1trap 'kill ${! (; term _ handler ' sigterm # runapplicationnodeapppid=' $! ' # waitforeverwhiletruedotail-f/dev/null wait $ {! }名为}done的脚本文件在启动APP应用程序的同时捕获发送的SIGTERM和SIGUSR1信号,并添加处理程序。 其中,SIGTERM信号的处理过程是向节点APP应用程序发送SIGTERM信号。
然后,按如下方式创建Dockerfile2文件:
接下来,创建镜像。
$ docker build-- no-cache-t signal-app2-fdockerfile2.然后启动容器以执行APP设置。
$ docker run-it-- RM-p 300033603000-- name=' my-app2 ' signal-app2此时,节点应用于容器的进程号也不是1,但是接收到SIGTERM信号
应用程序作为容器中的 1 号进程容器中的第一个过程非常重要,如果不能正确处理相关信号,APP的退出方式几乎总是被强制杀死,而不是优雅的退出。 因为谁是第一进程主要由输入点、CMD、RUN等指令的书写方式决定,所以对这些指令的使用很讲究。
应用程序不是容器中的 1 号进程