AFM*_*les 5 javascript node.js coffeescript docker dockerfile
我在我的应用程序中设置了监听器来捕捉 SIGTERM、SIGINT 和 SIGUSR2:
# kill
process.on 'SIGTERM', ->
killExecutors 'SIGTERM'
# ctrl + c
process.on 'SIGINT', ->
killExecutors 'SIGINT'
# nodemon signal
process.on 'SIGUSR2', ->
killExecutors 'SIGUSR2'
Run Code Online (Sandbox Code Playgroud)
它按预期工作。当我在 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"]
Run Code Online (Sandbox Code Playgroud)
一切正常,也是。但是,当我向执行添加节点标志时
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"]
Run Code Online (Sandbox Code Playgroud)
它停止捕捉信号。我试图将 de CMD exec 形式更改为
CMD ./node_modules/.bin/coffee --nodejs --max_old_space_size=384 feeder.coffee
Run Code Online (Sandbox Code Playgroud)
但仍然不起作用。带标志和不带标志的执行之间有什么变化?
编辑:
实际上,当没有传递任何标志时,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
Run Code Online (Sandbox Code Playgroud)
和传递标志时的两个过程
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
Run Code Online (Sandbox Code Playgroud)
问题是:为什么?
TL;DRcoffee当您需要使用扩展node选项来避免 Docker 下分叉进程的信号的技术性时,请使用 Javascript 加载程序文件而不是可执行文件。
require('coffee-script').register();
require('./whatever.coffee').run();
Run Code Online (Sandbox Code Playgroud)
然后
node --max_old_space_size=384 app.js
Run Code Online (Sandbox Code Playgroud)
现在,进入技术细节......
容器中的初始进程是容器命名空间中的 PID 1。PID 1(或 init 进程)被内核视为信号处理方面的特殊情况。
所以 docker 进程应该自己处理信号。
--nodejs选项正如您所指出的,当一个子进程可以选择传递额外的选项时,它coffee会派生出一个子node进程--nodejs。
这最初在docker之外通过信号处理(至少在 osx 上)呈现出一些奇怪的行为。A SIGINTorSIGTERM将被转发到子coffee进程,但也会立即终止父进程,无论您如何处理代码中的信号(在子进程中运行)。
一个简单的例子
process.on 'SIGTERM', -> console.log 'SIGTERM'
process.on 'SIGINT', -> console.log 'SIGINT'
cb = -> console.log "test"
setTimeout cb, 5000
Run Code Online (Sandbox Code Playgroud)
当你运行这个和ctrl- 时c,信号被转发到子进程并处理。父进程会立即关闭并返回到 shell。
$ coffee --nodejs --max_old_space_size=384 block_signal_coffee.coffee
^C
SIGINT
$ <5ish second pause> test
Run Code Online (Sandbox Code Playgroud)
然后带有您的代码的子进程继续在后台运行 5 秒钟并最终输出test.
coffee --nodejs主要问题是父coffee进程不处理代码中的任何信号,因此信号不会到达,也不会转发到子进程。这可能需要更改coffeescript 的启动器代码才能修复。
coffee --nodejs如果发生在 Docker 下,出现在 Docker 之外的信号怪癖也可能很糟糕。如果主容器进程(fork 的父进程)在您的信号处理程序有机会在子进程中完成之前退出,则容器将在它们周围关闭。如果仅通过将信号转发给孩子来解决上述问题,则这种情况不太可能发生。
使用建议的 javascript 加载器或修复咖啡脚本加载器的另一种方法是使用实际的 init 进程,例如runit或supervisor,但这会在docker和您的服务之间增加另一层复杂性。
| 归档时间: |
|
| 查看次数: |
1937 次 |
| 最近记录: |