Skip to content

Instantly share code, notes, and snippets.

@hankei6km
Last active February 26, 2018 03:23
Show Gist options
  • Save hankei6km/bd720737b9e7f27cf694c54409475c03 to your computer and use it in GitHub Desktop.
Save hankei6km/bd720737b9e7f27cf694c54409475c03 to your computer and use it in GitHub Desktop.
Docker のイベントを監視し、何らかのアクションを実行する(ワンライナー版)

Docker のイベントを監視し、何らかのアクションを実行する(ワンライナー版)

先日、「sam local start-api から実行されるコンテナの /var/task の中を確認しようとしたところ、コンテナがすぐに終了してしまうのでちょっとむずかしい」という状況があった.

という訳で、Dockerのイベント(コンテナがスタートした等)に対して何らかのアクションを自動的に実行するような仕組みがあれば便利かな、と思ったので試してみた.

イベントを監視してみる

イベントの監視には、以下の docker events を使う.

試しに $ sudo docker events を実行し、適当にコンテナの操作を行うことでイベントが表示されることを確認.

フィルタリング

今回は $ sam local start-api から実行されるコンテナの開始を捕捉したいので、以下のようにフィルターを指定する.

  • タイプは container
  • イベントは start
  • イメージは lambci/lambda
$ sudo docker events --filter type=container --filter event=start --filter image=lambci/lambda

コンテナの ID のみ表示する

アクション(今回は docker exec)の実行時にコンテナの ID を利用したいので、以下のように ID のみ表示するフォーマットを指定する.

$ sudo docker events --filter type=container --filter event=start --filter image=lambci/lambda --format '{{.Actor.ID}}'

アクションの実行

コンテナの ID を受け取って docker exec を実行する場合は以下のようにする.

$ sudo sh -c "docker events --filter type=container --filter event=start --filter image=lambci/lambda --format '{{.Actor.ID}}' | xargs -I{} docker exec -t '{}' ls -l /var/task"

これで、lambci/lambda を元にしたコンテナが開始される毎に指定したコマンドが実行されるようになる.

問題点

上記の例の場合だとコンテナが稼働している時間が短いので、以下のような結果となることも多い (他のエラーメッセージのパターンもあるが、ようはコンテナが動いてないと返ってくる).

Error response from daemon: Container 3fb957... is not running

あとは、パイプを他のコマンドに繋いだり、複数使ったりするとうまく出力されないことがある. awk を挟む場合は system("") を使ったり、その他では stdbuf -i0 -o0 を使うと回避できることもあるので、おそらくバッファ関連の問題かと推測しているのだけれども、根本的な原因と解決策はよくわかっていない.

参考: awk に標準出力をバッファさせないようにする

アクションの同時実行

上記の例では順次アクションを実行しているが、そこがボトルネックになる可能性がある. これについては、xargs を間に挟む場合は -P で同時に実行できるプロセス(アクション)数を指定できるようなので、 効率が気になる場合は -P を試してみるとよいかもしれない.

応用例1: イメージにタグ付けされたら通知を行う

標準入力の内容を通知するコマンド(今回の例では some_notify)を利用する場合、以下のようにする.

$ sudo docker events --filter type=image --filter event=tag --format '{{.Actor.Attributes.name}}' | xargs -I{} -P 3 -- sh -c "echo -e '\ntagged: {}\n' | some_notify"

この例では、xargs-P を指定しているので、通知は同時に3つまで実行されるはず (同時実行される状況を試していないのであまり自信はない).

応用例2: イメージ名が sha で始まるコンテナが exitCode!=0 で終了したら通知を行う

標準入力の内容を通知するコマンド(foo)があるとした場合、以下のようにする.

$ sudo docker events --filter type=container --filter event=die --format '{{.Actor.Attributes.image}},{{.Actor.Attributes.exitCode}}' | awk -F',' '/^sha/ && $2!=0{print $2; system("")}' | xargs -I{} -P 3 -- sh -c "echo -e '\ncontainer stopped. exit code={}\n' | some_notify"

この例では docker events のフィルター指定だけでは難しかったので、 awk を間に挟んでいる.

ちなみに、これを実行していると docker build がエラーで終了したときが大雑把に把握できる (実際には Dockerfile の構文エラー等は通知されない等、完全に把握はできないのだが).

Python 版

ワンライナー版でもお手軽で良い感じかなと思っているのだけれども、いろいろ拡張できるかなと思って Python でも試してみた.

よければ、そちらもどうぞ.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment