javascript - docker-compose 退出时运行可执行文件
问题描述
当docker容器退出时,我正在尝试使用nodejs执行一个javascript文件。这是我到目前为止所得到的,我的Dockerfile内容如下所示。我无法在退出期间捕获SIGINT信号,因此无法运行该int_handler()
函数。我在下面提供的脚本中是否有任何问题?
我运行命令docker-compose up
启动服务器,然后CTRL + C
退出。
FROM node:10.16.0-slim
ENV NPM_CONFIG_PREFIX=/home/node/.npm-global
ENV PATH=$PATH:/home/node/.npm-global/bin
RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
RUN mkdir -p /home/node/app/logs && chown -R node:node /home/node/app
WORKDIR /home/node/app
COPY package*.json ./
USER node
RUN npm install
COPY --chown=node:node . .
EXPOSE 8080
EXPOSE 8523
COPY ./docker-script.sh ./docker-script.sh
ENTRYPOINT ["./docker-script.sh"]
docker-script.sh文件的内容如下所示:
#!/bin/bash
set -x
pid=0
int_handler() {
echo "handler"
node deactivator & pid="$!"
}
# setup handlers
trap 'kill ${!}; int_handler' SIGINT
# run application
node server & pid="$!"
# wait forever
while true
do
tail -f /dev/null & wait ${!}
done
我的 docker-compose.yml 文件
version: '3'
services:
mongo:
image: mongo:3.6
web:
image: myimage/imagexyz:0.9.1
restart: always
ports:
- "80:8081"
- "443:8524"
links:
- mongo
depends_on:
- mongo
解决方案
这件事有几个小细节。
最重要的是,当您将Ctrl+发送C到前台docker-compose up
时,它会等效于docker-compose stop
,而后者又等效于docker stop
。那发送SIGTERM
,不SIGINT
。改变你的trap
线路以捕捉正确的信号会有所帮助。
在对此进行试验时,一旦您发送了Ctrl+ C,docker-compose up
将停止打印容器输出。它仍然会生成,但您仍然可以看到它docker-compose logs web
。
这个脚本似乎在后台运行了很多它不需要的东西,而让我跳出来的另一件事是你的int_handler
函数在容器即将退出时启动了一个后台进程。这也具有运行“以保持容器活动”的反模式tail -f
,而您的应用程序作为一种副作用运行。
我从你的脚本的这个修改中得到了合理的行为:
#!/bin/sh
int_handler() {
echo "int_handler"
# node deactivator
# forcibly exit the script (and the container)
exit 0
}
# trap SIGTERM here, not SIGINT
trap int_handler SIGTERM
echo start
# run the CMD from the Dockerfile or the `docker run` command
"$@" &
# wait for that process to exit
# (don't start an artificial `tail -f`)
# (you must `wait` or else the signal is delayed until
# the process exits on its own)
wait $!
和一个匹配的琐碎Dockerfile
:
FROM alpine
COPY script /
ENTRYPOINT ["/script"]
CMD ["sleep", "15"]
如果trap
函数没有exit
,那么最终之后的入口点脚本中的任何内容都wait
将执行。如果你想无条件地清理,你可以使用它。stop
即使您是容器,此变体也始终会打印docker stop
,并以脚本的退出状态退出。
#!/bin/sh
trap 'kill $pid' SIGTERM
echo start
"$@" &
pid=$!
wait $pid
rc=$?
echo stop
exit $rc
推荐阅读
- php - 如何替换包含冰岛字符的字符串?
- c++ - 如何在 C++ 中制作函数列表?
- json - 如何用 Alamofire 解析 json 数据?
- javascript - 将数据从 firebase 发送到 android 应用
- java - RxJava 2 - 如何在出错时取消无限流并处理它?
- python - interp2d 铸造裁定不“安全”
- java - 用Java实现一个基本的FTP客户端
- javascript - 创建一个交叉过滤器“插件”
- python - 在python中使用自省获取swagger生成的模型的属性
- queue - WSO2 esb 处理器将消息发送到队列,其他处理器从队列接收特定消息