🐳

コンテナで定期実行したいときにどれが良いか?

2021/01/17に公開6

背景

一定間隔で実行するアプリを付く場合が多々あります。
その時の定石なのを作っておきたくて少し調べたので、ここにまとめておきます。

個人的な結論

これは個人的な結論ですが、デプロイする環境に合わせる必要があると思っています。
つまりコンテナをどのサービスで実行するかによって、切り替える必要があるってことです…(メンどぉ)

kubernetes

kubernetesではCronJobという機能があり、特定のPodをCron的なスケジュールで定期実行する事ができます。
この場合はDockerFileは下記のような形で問題ないと思います。

FROM debian
CMD [ "echo","'hi'" ]

コンテナ管理サービス

GCPのCloud RUNなどで実行する場合
これをHTTP経由で定期的に呼び出すサービスがあります。
ですので、HTTPサーバを立ててそれ経由で呼び出す方法が一般的だと思います。

FROM python:3
RUN pip install flask
ADD ./main.py /root/main.py
CMD [ "python","/root/main.py" ]
main.py
from flask import Flask
app = Flask(__name__)

@app.route('/')
def hi():
    print("hi")
    return 'hi!'

if __name__ == '__main__':
    app.run(host='0.0.0.0',port=80)

その他

いくつか調べたのですが、やはりプログラム内から定期実行させるのが一般的っぽい気がします…
なにやら負けた気がしますが…
他の案がある方はコメントを下さい!

FROM python:3
ADD ./main.py /root/main.py
CMD [ "python","/root/main.py" ]
main.py
import time
while(True):
    time.sleep(20)
    print("hi")

下記で述べるように、Cronやwatchでも試しましたが、docker logs xxxでログを参照できないのが個人的にNGでした。

調べたこと

Cron実行

LinuxでおなじみのCron先生で定期実行する案です。
これを行うとフロント側でCron先生が実行されてしまい。ログなどの出力が行われません…

FROM debian
RUN apt update && apt -y install cron
RUN echo '*/1 * * * * echo "hi"' >> /etc/crontab
CMD ["cron", "-f"]

watch実行

特定のコマンドを定期実行し、その結果を表示し続けるコマンドです。
表示が目的であるためか…出力が文字化けしてしまい確認ができません…

FROM debian
RUN apt update && apt -y install watch
CMD ["watch", "-n", "1","echo 'hi'"]

コメント

私が二日酔いの頭で考えられるのはこの程度でした…
他の良い案がある方はコメントを下さい!

Discussion

hashitohashito

コメントありがとうございます!
昔、そちらの方法で定期実行したかったのですが、認証無しでやると未知の呼び出しでおかしくなってしまいそうな気がして、認証実装しようとして断念した記憶があります…

先程、見てみたら内部からの通信のみを許可するという認証やらなくても良さそうなオプションが追加されました!
このオプションで教えていただいたCloudScheduler呼び出しが許容されていたらかんたんですね!

hashitohashito

内部からの通信というのはVPCネットワークからの通信のみのことを指すようです…
https://cloud.google.com/run/docs/securing/ingress?hl=JA&_ga=2.237044421.-452786259.1593029253

ただ、サービスアカウントを作って紐付けて実行したところ、うまく回りました!
これで進めたいと思います。ありがとうございます!

catnosecatnose

おー、なるほど!
詳しく教えていただきありがとうございます!!

onotmonotm

cron実行のところですが、コマンドの出力をPID1のstdout/stderrにリダイレクトすればコンテナログとして表示可能なんじゃないでしょうか?

 FROM debian
 RUN apt update && apt -y install cron
-RUN echo '*/1 * * * * echo "hi"' >> /etc/crontab
+RUN echo '*/1 * * * * echo "hi" 1>>/proc/1/fd/1 2>>/proc/1/fd/2' >> /etc/crontab
 CMD ["cron", "-f"]
hashitohashito

コメントを頂きありがとうございます!
頂いたコードを試してみましたが、何故か書き込みが行われていないような状態なようです…
もう少し私も探ってみたいと思います…
(お話的にはうまく行きそうな感じがするのですが…)