カテゴリー
[Node.js & Docker] node-cronをDockerコンテナから使ってスケジュール実行をさせてみる
※ 当ページには【広告/PR】を含む場合があります。
2020/09/06
首題のように
はじめに
ですがこれだと、ホストOSがcronの使えないWindowsなどのLinux以外のOSではこの方法が利用できません。
そんなときにはnode-cronを利用することで、コンテナ内のnode.jsで実装したプログラムをcronのように定期実行できるようになります。
この場合には、ホストOSのデーモン機能が無くてもコンテナを常時起動しているだけで簡単なスケジューラーとすることが可能です。
Dockerコンテナの構築
例のように例のごとくDockerとdocker-composeのインストール済みの環境であることが前提です。
これらのインストール方法などは割愛させていただきます。
手元の環境は以下の通りですが、ホストOSはDockerが動作すればOKです。
$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 10 (buster)
Release: 10
Codename: buster
$ docker -v
Docker version 19.03.8, build afacb8b7f0
$ docker-compose -v
docker-compose version 1.16.1, build 6d1ac21
プロジェクトのファイル構造の下準備
まず今回の内容を試すのに必要最低限のファイル・フォルダを以下のように与えておきましょう。
どこかの適当なフォルダに移って、以下のようにします。
$ touch Dockerfile docker-compose.yml index.js package.json && mkdir tmp
$ tree
.
├── Dockerfile
├── docker-compose.yml
├── index.js
├── package.json
└── tmp #👈空のフォルダ
以下ではこのリソースファイルの中身を編集していきます。
Dockerfile
ベースイメージは
FROM node:12-alpine
ENV NODE_ENV development
WORKDIR /usr/src/app
COPY package.json ./
RUN yarn install && yarn cache clean
CMD ["node", "index.js"]
docker-compose.yml
Dockerイメージのビルドにdocker-composeを使います。
docker-composeのサービス名は
cron
version: '3'
services:
cron:
image: node-cron-dckr:12-alpine
build: .
container_name: my-node-cron
user: 'node:node'
environment:
NODE_ENV: development
volumes:
- ./:/usr/src/app
tty: true
index.js
cronのスケジュール文法に関しては後述しています。
毎分実行する相当の
* * * * *
tmp
const cron = require('node-cron');
const fs = require("fs");
cron.schedule('* * * * *', () => {
try{
console.log('running a task every minute');
fs.appendFileSync("tmp/file.txt", "Hello Node-Cron!\n");
}
catch(e){
console.log(e.message);
}
});
package.json
package.jsonを以下の内容で与えておきます。
{
"name": "node-cron-dckr",
"version": "0.0.1",
"devDependencies": {
"node-cron": "^2.0.0"
}
}
ここは、
devDependencies
RUN yarn add node-cron -D
イメージのビルド
以上のDockerイメージをビルドします。
$ docker-compose build
$ docker images
REPOSITORY TAG IMAGE ID SIZE
node-cron-dckr 12-alpine 76bed01fec57 104MB
これで今回のイメージがスタンバイできました。
Cronのスケジュール文法
cronを扱ったことのある方なら分かっていらっしゃると思います。
まずはちょこっとだけcronのスケジュール表記の復習です。
cronのタスクをスケジュールするのに、スペース切りの5つの数字かアスタリスクの羅列する箇所(
* * * * *
この5つの数値でcronのスケジュールが管理されます。
cat /etc/crontab
Example of job definition:
.---------------- minute (0 - 59)
| .------------- hour (0 - 23)
| | .---------- day of month (1 - 31)
| | | .------- month (1 - 12) OR jan,feb,mar,apr ...
| | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
| | | | |
* * * * * user-name command to be executed
と説明書きがあります。
ざっと左から、分、時、日、月、曜日、となります。
any
*
例えば、よくあるパターンの
* * * * *
* * * * 1:
月曜日限定で毎分実行
10 * * * *:
毎時間、時計の針が10分になったら実行
(..., 8:10, 9:10, 10:10, ...)
20 8 * * *:
毎日午前8時20分になったら実行
あと当然ですが、秒単位での実行指定はcronではできません。
なので、別のタイマーライブラリなどを利用することになります。
コンテナの起動
ではデタッチモード(バックグラウンド)で起動します。
$ docker-compose run -d cron
しばらく経ってから、
tmp
$ cat tmp/file.txt
Hello Node-Cron!
Hello Node-Cron!
Hello Node-Cron!
Hello Node-Cron!
#...以降一分毎に更新
止め方・消し方
今回はnode-cronのテスト程度ですのでいつまでも動かしている必要がないため、終わったら止めておきます。
まずは
docker ps
$ docker ps
CONTAINER ID IMAGE COMMAND STATUS NAMES
0639a40822ed node-cron-dckr:12-alpine "docker-entrypoint.s…" Up nodecrondckr_cron_run_1
なおdocker-composeで起動したコンテナ名は、
<イメージ名>_<サービス名>_run_<起動しているコンテナ数>
#👇コンテナを止める場合
$ docker stop nodecrondckr_cron_run_1
nodecrondckr_cron_run_1
#👇コンテナを消す場合
$ docker rm nodecrondckr_cron_run_1
nodecrondckr_cron_run_1
まとめ
node-cronを使えば、cronデーモンのdocker版のようなプログラムが簡単に作成できます。
shellプログラミングが苦手な方も簡単にスケジューラーがカスタマイズできます。
また今回紹介した方法ならばdockerが使える環境は必要ですがホストOSは問わないので、共通したプログラムで同じ結果が得られるのがメリットです。
参考サイト
記事を書いた人
ナンデモ系エンジニア
主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。
カテゴリー