我有一个要定期运行的node
脚本,因此我创建了以下Dockerfile
以从cron
任务运行它:
FROM node:8
RUN apt-get update && apt-get install -y cron
# ensure the node packages are installed in the image
WORKDIR /usr/src/app
COPY package.json .
RUN npm install
# copy the node task to working directory
COPY db-update.js .
# copy the script which will start cron to the working directory
COPY startcron.sh .
# copy the cron task to the cond.d directory
COPY crontask /etc/cron.d/crontask
# give execution rights on the cron job and script
RUN chmod 0644 /etc/cron.d/crontask && chmod 777 ./startcron.sh
# apply the cron job
RUN crontab /etc/cron.d/crontask
# create the log file to be able to run tail
RUN touch /var/log/cron.log
# execute the command in the foreground
CMD /usr/src/app/startcron.sh
在startcron.sh
bash脚本中,我具有以下内容:
#!/bin/bash
set -e
printenv | sed 's/^\(.*\)$/export \1/g' > /tmp/env.sh
echo 'Starting cron' # <- ONLY THIS APPEARS IN MY CONTAINER LOGS
cron -f
我需要创建/tmp/env.sh
来导出我的node
脚本所需的环境变量。然后,该脚本应在前台开始cron
。我的crontask
应该“获取”这些环境变量并运行我的node
脚本。如果一切设置正确,我希望在Docker容器的日志中看到节点脚本的输出。
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12)
# │ │ │ │ ┌───────────── day of week (0 - 6) (Sunday to Saturday;
# │ │ │ │ │ 7 is also Sunday on some systems)
# │ │ │ │ │
# │ │ │ │ │
# * * * * * command to execute
# DOES THIS COMMAND EXECUTE SUCCESSFULLY, IF NOT WHY NOT?
*/5 * * * * . /tmp/env.sh /usr/local/bin/node /usr/src/app/db-update.js > /proc/1/fd/1 2>/proc/1/fd/2
# need to leave an empty line
这是我的节点脚本的片段:
const sftpclient = require('ssh2-sftp-client');
const expressGraphQL = require('express-graphql');
const mongoose = require('mongoose');
const fs = require('fs');
console.log('now executing db-update');
const IN_PRODUCTION = (process.env.NODE_ENV === 'production' ? true : false);
console.log('what is node env: ', process.env.NODE_ENV);
console.log('what is env: ', process.env);
但是,当我运行此容器时,在容器日志中看到的唯一输出是bash脚本“启动Cron”中的echo命令。我看不到节点脚本的任何输出,但是容器继续运行。如何确保node
脚本能够运行,或者如果容器没有运行,该容器是否会失败?
答案 0 :(得分:1)
为了使您的生活更轻松,我建议您更改策略以使用带有睡眠的简单无限循环而不是cron
所以在CMD中只是放置
while true; sleep 300; execute-node-program || exit 1; done
在这种策略中:
使用cron很难实现这一点,因为您可能需要将systemd放置在两个进程中:
编辑:
因此,让您了解在cron作业失败时如何处理杀死容器的问题:
--init
标志来启动容器,例如docker run --init ...-这真的很重要,它可以让您从容器中杀死主要容器的进程*/5 * * * * bash -c "/tmp/env.sh && /usr/local/bin/node /usr/src/app/db-update.js || pkill -9 -f cron" > /proc/1/fd/1 2>/proc/1/fd/2