最近AWS ECS、Fargate、Batchとコンテナに囲まれた生活を送っていた。
そんな中で「コンテナプロセスのリトライ処理出来るBatch君すごい!AWS様すごい!」とか思ってて、仮に自前でリトライ処理やろうと思ったらどうやればいいんだろうとか思いながら、Dockerドキュメントを読み漁ってたらDocker run リファレンス内に restart
フラグを見つけて感動したので記事にした。
tl;dr
-
docker container run
コマンド実行時に引数として--restart=on-failure:xx
を渡すとリトライ処理が可能(xx=整数) - リトライ処理の実行条件はコンテナプロセス終了コードが0以外の場合
- リトライされたコンテナプロセスはバックグラウンドプロセスで実行される
本当にリトライされるか検証
検証環境
- macOS 10.13.1, Darwin 17.2.0
- Docker version 18.06.1-ce
ディレクトリ構成
いつも自分が作業するディレクトリの下に以下のディレクトリ構成を作成する。
ディレクトリ名: retry_container
retry_container
.
├── Dockerfile
└── date.log
0 directories, 2 files
検証用Dockerfile
以下の内容を作成したDockerfile内に貼り付ける。
FROM alpine:3.8
CMD date >> /tmp/date.log && echo "container run!" && exit 1
このDockerfileで作成されるコンテナの振る舞いとしては以下の通り。
-
date
コマンドの標準出力を/tmp/date.log
に書き込む -
echo
コマンドでホストマシン側に実行されたと分かる文字列を出力 -
exit
コマンドに引数として1
を渡し、プロセス終了コード1
としてコンテナプロセスを終了させる
date.log
touchだけでOK。
$ touch date.log
コンテナイメージを作成
Dockerfile
とdate.log
が用意できたらビルドする。
$ docker build -t retry_container .
Successfully built というメッセージが流れたらビルド成功。
コンテナを実行してみる
$ docker container run -v $HOME/work/retry_container/:/tmp/ retry_container:latest
-vオプションを用いて、ホストマシンの$HOME/work/retry_container/
ディレクトリ以下の内容をコンテナ内の /tmp/
ディレクトリ以下にマウントしている。
$HOME/work/
部分のファイルパスに関しては自分の環境に合わせて書き換える必要有り。
実行結果は以下の通り
container run!
$ cat ./date.log
Thu Sep 13 17:18:52 UTC 2018
ホストマシン側には標準出力として echo
で出力した文字列とdate.log
ファイル内にはコンテナ内で実行したdate
コマンドのUTC時刻が書き込まれているはず。
書き込まれていれば、コンテナの実行は成功。
restart
フラグを付与してコンテナを実行してみる
$ docker container run --restart=on-failure:10 -v $HOME/work/retry_container/:/tmp/ retry_container:latest
restart
フラグに与える引数はon-failure:10
なのでリトライ処理試行回数は10回となる。
実行結果
container run!
出力を見た感じrestart
フラグを付ける前と変わっていない感じがする。
しかし、date.log
ファイルの中身が大きく変わってくるはずだ。
$ cat ./date.log
Thu Sep 13 17:18:52 UTC 2018
Thu Sep 13 17:35:35 UTC 2018
Thu Sep 13 17:35:37 UTC 2018
Thu Sep 13 17:35:38 UTC 2018
明らかに自分が実行した回数以上にdate.log
ファイルにdate
コマンドの出力が書き込まれているはず。
docker container run --restart=on-failure:10 -v $HOME/work/retry_container:/tmp/ retry_container:latest
を実行して、数十秒の間にdocker container ls
コマンドを実行してみよう。
すると、現在実行されているコンテナとしてretry_container:latest
がまだ実行されているはず。
なぜdate.log
は書き込まれているのに、echo
がホストマシン側に出力されないかというと、リトライされたコンテナプロセスはバッググラウンドプロセスで実行されるからだ。
数分待ったあとにdocker container ls
を実行して、retry_container:latest
コンテナが実行されていなければ10回分のリトライ処理が終了したということになる。
確認してみよう。
$ cat ./date.log | wc -l
12
書かれた手順通りに進めたなら12
という数字が出力されるはず。
- コンテナが正しく実行されるかどうかの確認として1回
- リトライ処理に入る前に実行されたので1回
- リトライ処理として10回
restart
フラグに引数として渡した値分リトライ処理されていることが分かった。
リトライインターバルに関しては不明。
時間があれば調べてみよう。。
リトライ処理される度にインターバルが長くなっている気はする。
所感
AWS Batchのリトライ処理に関してはrestart
フラグ使ってリトライ処理を実現してそう。
改めてリファレンスは時間のある時に目を通した方が良いなというのを強く感じた。