Dockerコンテナで定期的(分次、時次、日次、週次、月次など)で実行したいときに、
Cronは有効な解決方法です。
この記事では、Dockerコンテナ内で"環境変数込みで"Cronを実行する方法をまとめました。
目次
Dockerコンテナで"環境変数込みで"Cronを実行するには?
DockerコンテナでCronを実行するには以下の2パターンがあると思います。
ここではポータビリティを重視するため、前者の「コンテナにCronを実装する方法」を採用して説明します。
Dcokerコンテナで"環境変数込みで"Cronを実行する方法
- コンテナ内のCronで実行する
・ホストに依存しないため、ポータビリティが高い
・ホストの環境変数が使えないため、いろいろな工夫が必要
- ホストのCronからdocker execコマンド等でコンテナ内の処理を実行する
・ホストに依存してしまうため、ポータビリティが下がる
コンテナ内のCronで実行する方法
Dockerコンテナ内のcronでは、ホストPCからコンテナ内に注入された環境変数が反映されないため、
いろいろと工夫する必要があります。[1]
そのため、「実行スクリプト(runCronProcess.sh)」と「環境変数リスト化スクリプト(initEnv.sh)」、「環境変数設定スクリプト(env.sh)」の3つのスクリプトで実装します。
3つのスクリプトの概要
- 実行スクリプト(runCronProcess.sh)
・cronで呼び出されるスクリプト
・「環境変数設定スクリプト」を実行した後に、ターゲットの処理を実行する
- 環境変数リスト化スクリプト(initEnv.sh)
・Dockerコンテナが起動したときに呼び出されるスクリプト
・コンテナに注入された環境変数から「環境変数設定スクリプト」を生成する
- 環境変数設定スクリプト(env.sh)
・実行スクリプトで呼び出されるスクリプト
・コンテナに注入された環境変数を設定する
必要なファイルを作成する
コマンド実行
(ホストPCで)
$ touch Dockerfile
$ touch runCronProcess.sh
$ sudo chmod +x runCronProcess.sh
$ touch initEnv.sh
$ sudo chmod +x initEnv.sh
DockerFileを記述する
Dockerfile(例)
FROM python:3.11
ENV PYTHONUNBUFFERED=1
RUN apt-get update
RUN apt-get install -y cron
RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
RUN mkdir /log && mkdir /script
COPY /initEnv.sh /script/
COPY /runCronProcess.sh /script/
RUN echo '*/1 * * * * root date >> /log/test.log 2>&1' >> /etc/crontab
ENV MYNAME=shiguregaki
RUN echo '*/1 * * * * root echo 1. $MYNAME >> /log/test.log 2>&1' >> /etc/crontab
RUN echo '*/1 * * * * root . /script/runCronProcess.sh' >> /etc/crontab
ENTRYPOINT ["/script/initEnv.sh"]
・赤色下線のところが本命の処理(1分間隔で呼び出されるようにしています)です。黄色下線は動作確認のときに比較できるように追加した処理のため、削除しても構いません。
スクリプトを記述する
runCronProcess.sh
#!/bin/sh
. /root/env.sh
echo 2. $MYNAME >> /log/test.log 2>&1
・「. /root/env.sh
」の下にcronで実行させたい処理を追加していきます。
initEnv.sh
#!/bin/bash -e
printenv | awk '{print "export " $1}' > /root/env.sh
cron
実行してみる
以下のコマンドを実行してDockerコンテナを起動します。
コマンド実行(例)
(ホストPCでDockerfileのディレクトリに移動)
$ docker image build -t test-image:v1 .
$ docker run --name test-container1 -it test-image:v1 /bin/bash
root@xxxxxxxxxxxxx:/#
cronの結果はコンテナ内の/log/test.logに出力しています。
中身を確認すると以下のように、crontab内で直接環境変数を呼び出したケース(1.)は何も表示されていないのに対して、実行スクリプトで環境変数を呼び出したケース(2.)は意図した値が表示されています。
test.log(ログ出力)
Sun Feb 26 23:49:01 JST 2023
1.
2. shiguregaki
参考
[1] Docker コンテナ内でタスクを cron 起動する
[2] Docker コンテナ内で cron を実行し実行ログを出力する方法
以上!
コメント