在 docker 容器中捕获信号

前端之家收集整理的这篇文章主要介绍了在 docker 容器中捕获信号前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

关闭容器或者把某个信号传递给容器中的进程。这些操作的本质都是通过从主机向容器发送信号实现主机与容器中程序的交互。比如我们可以向容器中的应用发送一个重新加载信号,容器中的应用程序在接到信号后执行相应的处理程序完成重新加载配置文件的任务。本文将介绍在 docker 容器中捕获信号的基本知识。

注册处理程序,比如为了能让程序优雅的退出(接到退出的请求后能够对资源进行清理)一般程序都会处理 SIGTERM 信号。与 SIGTERM 信号不同,SIGKILL 信号会粗暴的结束一个进程。因此我们的应用应该实现这样的目录:捕获并处理 SIGTERM 信号,从而优雅的退出程序。如果我们失败了,用户就只能通过 SIGKILL 信号这一终极手段了。除了 SIGTERM 和 SIGKILL ,还有像 SIGUSR1 这样的专门支持用户自定义行为的信号。下面的代码简单的说明在 nodejs 中如何为一个信号注册处理程序:

process.on('SIGTERM','shutting down...'

》一文中有所提及,这里不再赘述。

用户可以指定等待的时间),就再发送一个 SIGKILL 信号强行结束程序。

文件,内容如下:

'use strict'<span style="color: #0000ff">var http = require('http'<span style="color: #000000">);

<span style="color: #0000ff">var server = http.createServer(<span style="color: #0000ff">function<span style="color: #000000"> (req,res) {
res.writeHead(200,{'Content-Type': 'text/plain'<span style="color: #000000">});
res.end('Hello World\n'<span style="color: #000000">);
}).listen(3000,'0.0.0.0'<span style="color: #000000">);

console.log('server started'<span style="color: #000000">);

<span style="color: #0000ff">var signals =<span style="color: #000000"> {
'SIGINT': 2<span style="color: #000000">,'SIGTERM': 15<span style="color: #000000">
};

<span style="color: #0000ff">function<span style="color: #000000"> shutdown(signal,value) {
server.close(<span style="color: #0000ff">function<span style="color: #000000"> () {
console.log('server stopped by ' +<span style="color: #000000"> signal);
process.exit(128 +<span style="color: #000000"> value);
});
}

Object.keys(signals).forEach(<span style="color: #0000ff">function<span style="color: #000000"> (signal) {
process.on(signal,<span style="color: #0000ff">function<span style="color: #000000"> () {
shutdown(signal,signals[signal]);
});
});

注册了处理程序。接下来我们将介绍以不同的方式在容器中运行程序时信号的处理情况。

文件,把上面的应用打包到镜像中:

/app.js .//package.json ./,]

$ docker build --no-cache -t signal-app -f Dockerfile .

$ docker run -it -- -p : --name= signal-app

退出,执行命令:

$ docker container --signal= my-app

退出:

文件 app1.sh,内容如下:

#!/usr/bin/

文件,内容如下:

/app.js .//app1. ./app1./package.json ./ +x ./app1.]

$ docker build --no-cache -t signal-app1 -f Dockerfile1 .

$ docker run -it -- -p : --name= signal-app1

退出程序了!在这个场景中,应用程序由 bash 脚本启动,bash 作为容器中的 1 号进程收到了 SIGTERM  信号,但是它没有做出任何的响应动作。

$ docker container stop my- --signal= my-app1

退出应用,它们最终都是向容器中的 1 号进程发送了 SIGKILL 信号。很显然这不是我们期望的,我们希望程序能够收到 SIGTERM  信号优雅的退出

文件 app2.sh,内容如下:

#!/usr/bin/-pid=<span style="color: #800080">0<span style="color: #000000">

SIGUSR1-<span style="color: #000000">handler

my_handler() {
<span style="color: #0000ff">echo <span style="color: #800000">"<span style="color: #800000">my_handler<span style="color: #800000">"<span style="color: #000000">
}

SIGTERM-<span style="color: #000000">handler

term_handler() {
<span style="color: #0000ff">if [ $pid -ne <span style="color: #800080">0 ]; <span style="color: #0000ff">then
<span style="color: #0000ff">kill -SIGTERM <span style="color: #800000">"<span style="color: #800000">$pid<span style="color: #800000">"
<span style="color: #0000ff">wait <span style="color: #800000">"<span style="color: #800000">$pid<span style="color: #800000">"
<span style="color: #0000ff">fi<span style="color: #000000">
exit <span style="color: #800080">143; # <span style="color: #800080">128 + <span style="color: #800080">15 --<span style="color: #000000"> SIGTERM
}

setup handlers

on callback,<span style="color: #0000ff">kill the <span style="color: #0000ff">last background process,<span style="color: #0000ff">which is <span style="color: #0000ff"&gt;tail</span> -f /dev/<span style="color: #0000ff"&gt;null</span><span style="color: #000000"&gt; and execute the specified handler

trap <span style="color: #800000">'<span style="color: #800000">kill ${!}; my_handler<span style="color: #800000">'<span style="color: #000000"> SIGUSR1
trap <span style="color: #800000">'<span style="color: #800000">kill ${!}; term_handler<span style="color: #800000">'<span style="color: #000000"> SIGTERM

run application

node app &<span style="color: #000000">
pid=<span style="color: #800000">"<span style="color: #800000">$!<span style="color: #800000">"<span style="color: #000000">

<span style="color: #0000ff">wait<span style="color: #000000"> forever

<span style="color: #0000ff">while <span style="color: #0000ff">true
<span style="color: #0000ff">do
<span style="color: #0000ff">tail -f /dev/<span style="color: #0000ff">null & <span style="color: #0000ff">wait ${!<span style="color: #000000">}
<span style="color: #0000ff">done

文件在启动应用程序的同时可以捕获发送给它的 SIGTERM 和 SIGUSR1 信号,并为它们添加了处理程序。其中 SIGTERM 信号的处理程序就是向我们的 node 应用程序发送 SIGTERM 信号。

文件,内容如下:

/app.js .//app2. ./app2./package.json ./ +x ./app2.]

$ docker build --no-cache -t signal-app2 -f Dockerfile2 .

$ docker run -it -- -p : --name= signal-app2

退出了:

退出的方式几乎总是被强制杀死而不是优雅的退出。究竟谁是 1 号进程则主要由 EntryPoint,CMD,RUN 等指令的写法决定,所以这些指令的使用是很有讲究的。

猜你在找的Docker相关文章