我在我的应用程序中设置了侦听器来捕获SIGTERM,SIGINT和SIGUSR2:
# kill
process.on 'SIGTERM', ->
killExecutors 'SIGTERM'
# ctrl + c
process.on 'SIGINT', ->
killExecutors 'SIGINT'
# nodemon signal
process.on 'SIGUSR2', ->
killExecutors 'SIGUSR2'
它按预期工作。当我在docker实例中运行它时:
FROM node:4.4.7
MAINTAINER Newborns <newborns@versul.com.br>
COPY . /src
EXPOSE 7733
WORKDIR /src
RUN npm install
CMD ["./node_modules/.bin/coffee", "feeder.coffee"]
一切都很好。但是,当我向执行
添加节点标志时FROM node:4.4.7
MAINTAINER Newborns <newborns@versul.com.br>
COPY . /src
EXPOSE 7733
WORKDIR /src
RUN npm install
CMD ["./node_modules/.bin/coffee", "--nodejs", "--max_old_space_size=384", "feeder.coffee"]
它停止捕捉信号。我试图将de CMD exec表单更改为
CMD ./node_modules/.bin/coffee --nodejs --max_old_space_size=384 feeder.coffee
但仍然无效。有和没有标志的执行之间有什么变化?
修改
实际上,当没有传递标志时,docker会启动一个进程
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 4.2 1.0 960940 85424 ? Ssl 20:21 0:01 node ./node_modules/.bin/coffee feeder.coffee
root 16 0.1 0.0 20220 2884 ? Ss 20:22 0:00 bash
root 20 0.0 0.0 17500 2064 ? R+ 20:22 0:00 ps -aux
和传递标志时的两个进程
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.1 0.3 707704 25272 ? Ssl 20:17 0:00 node ./node_modules/.bin/coffee --nodejs --max_old_space_size=384 feeder.coffee
root 10 1.7 1.1 965900 90068 ? Sl 20:17 0:01 /usr/local/bin/node --max_old_space_size=384 /src/node_modules/.bin/coffee feeder.coffee
问题是:为什么?
答案 0 :(得分:4)
TL; DR 当您需要使用扩展coffee
选项时,使用Javascript加载程序文件而不是node
可执行文件,以避免Docker下具有分叉进程的信号的技术性。
require('coffee-script').register();
require('./whatever.coffee').run();
然后
node --max_old_space_size=384 app.js
现在,关于技术性......
容器中的初始进程是容器命名空间中的PID 1。 PID 1(或init进程)被内核视为信号处理的特例。
因此,预期docker进程本身会处理信号。
--nodejs
选项如您所知,coffee
将fork a child node
process when it has the --nodejs
选项可以传递额外选项。
这最初会出现一些奇怪的行为在之外的与信号处理(至少在osx上)。无论您如何处理代码中的信号(在子代中运行),SIGINT
或SIGTERM
都会转发到子级,但也会立即终止父coffee
进程。
一个简单的例子
process.on 'SIGTERM', -> console.log 'SIGTERM'
process.on 'SIGINT', -> console.log 'SIGINT'
cb = -> console.log "test"
setTimeout cb, 5000
当你运行它并且 ctrl - c 时,信号被转发到子进程并进行处理。父进程立即关闭并返回shell。
$ coffee --nodejs --max_old_space_size=384 block_signal_coffee.coffee
^C
SIGINT
$ <5ish second pause> test
然后,使用您的代码的子进程继续在后台运行5秒钟,最终输出test
。
coffee --nodejs
主要问题是父coffee
进程无法处理代码中的任何信号,因此信号不会到达并且不会转发给孩子。这可能需要更改coffeescript's launcher code才能修复。
如果在Docker下发生,那么在Docker之外呈现的信号怪coffee --nodejs
也可能是坏的。如果主要容器进程(fork的父进程)在信号处理程序有机会在子进程中完成之前退出,则容器将在它们周围关闭。如果仅通过将信号转发到孩子上来解决上述问题,则不太可能发生这种情况。
使用建议的javascript加载器或修复咖啡脚本加载器的替代方法是使用实际的初始化过程,如runit或supervisor,但这会在docker和您之间增加另一层复杂性服务。