Dockerコンテナをホスト側のcronで実行する
やりたいこと
- とあるプログラムを実行するDockerコンテナを毎日定刻に起動したい。
- 処理が完了したらコンテナは消去したい。
つまり、次のコマンドをcronで実行したい。
$ docker run -it --rm my_image my_command
やったこと
crontabにそのまま書けばいいじゃん!
と思ったが、そうは東京医科歯科大学。
$ crontab -e 0 7 * * * docker run -it --rm my_image my_command
定刻になっても、うんともすんともしない。
まずは、crontabの実行環境で、dockerコマンドにパスが通ってんのかが気になった。
$ which docker /usr/bin/docker $ crontab -e * * * * * echo $PATH > /tmp/env.txt
結果は、
$ cat /tmp/env.txt PATH=/usr/bin:/bin
.bash_profile
に書いてあるようなユーザ定義の環境変数は受け継がれていないが、
少なくともdockerコマンドへのパスは通っているようだ。
デフォルトの/var/log/cronログファイルには、実行結果までは出力されない。
そこで、エラーチェックのために、次のように設定した。
* * * * * docker run -it --rm my_image my_command > /tmp/cron.log 2>&1
結果は、
$ cat /tmp/cron.log the input device is not a TTY
となっていた。 実端末(TTY)からの入力でないことで怒られている。
原因はイカの通り。
cronで指定されたコマンドは実端末から実行される訳ではない。
実際、
$ crontab -e * * * * * tty > /tmp/tty.txt
とすると、
$ cat /tmp/tty.txt not a tty
となる。
docker runコマンドの-itオプションは、
実行時の端末をコンテナ内のプロセスに割り当てるものであるため、
割り当てるべき端末がない、と怒っていたのだ。
結論
crontabには、次のように書けば良いです。(毎朝7時に実行したい場合)
0 7 * * * docker run --rm my_image my_command
こうしてできたのが、↓のbotです。
以上です。