【问题标题】:Running an executable when the docker-compose exitsdocker-compose 退出时运行可执行文件
【发布时间】:2020-02-14 09:36:56
【问题描述】:

我正在尝试在 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

【问题讨论】:

    标签: javascript node.js shell docker docker-compose


    【解决方案1】:

    这件事有几个小细节。

    最重要的是,当您将 Ctrl+C 发送到前台 docker-compose up 时,它相当于 docker-compose stop,而这又是相当于docker stop。那发送SIGTERM,而不是SIGINT。更改您的 trap 行以捕捉正确的信号会有所帮助。

    在对此进行试验时,一旦您发送了 Ctrl+Cdocker-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 之后的入口点脚本中的任何内容都将执行。如果你想无条件地清理,你可以使用它。即使您 docker stop 容器,此变体始终会打印 stop,并以脚本的退出状态退出。

    #!/bin/sh
    trap 'kill $pid' SIGTERM
    echo start
    "$@" &
    pid=$!
    wait $pid
    rc=$?
    echo stop
    exit $rc
    

    【讨论】:

    • 我想我遗漏了一些东西,但是如果你需要使用& 将命令放在后台,这意味着如果你不使用& 执行脚本将一直停留在该点,直到过程以某种方式关闭。然后你可以打印或做任何你需要的事情,而不必使用wait,对吧?
    • 如果前台进程正在运行,a trap won't trigger until it exits,这就是为什么这里你需要在后台启动进程,然后立即wait为它。
    • 我不明白你的意思?也许我误解了 OP 的要求,但我认为这个想法是在进程退出之后做某事,而不是在它之前?这就是为什么我说你可以没有陷阱,只做顺序操作
    • 这正是我所需要的。谢谢
    猜你喜欢
    • 2021-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-24
    • 2021-06-13
    • 2023-03-09
    • 2022-06-11
    • 1970-01-01
    相关资源
    最近更新 更多