Dockerホストで新しいコンテナが起動したり既存のコンテナが停止したタイミングで何らかの処理を実行したい場合があります。例えば、リバースプロキシの設定を反映したり、コンテナのURLをレビュアに通知したりといった用途が考えられます。
本記事ではdockerコマンドやRemote APIでイベントを取得して処理する方法を説明します。
docker eventsコマンドを使う
docker events
コマンドを実行すると、イベントが発生した場合に以下のような行が出力されます。
[2014-10-05 03:18:08 +0900 JST] 9f732da00641498f383779b58168b5e84aa21b5130bd7b9ed196220dea6d428b: (from centos:centos7) create [2014-10-05 03:18:08 +0900 JST] 9f732da00641498f383779b58168b5e84aa21b5130bd7b9ed196220dea6d428b: (from centos:centos7) start [2014-10-05 03:18:09 +0900 JST] 9f732da00641498f383779b58168b5e84aa21b5130bd7b9ed196220dea6d428b: (from centos:centos7) die [2014-10-05 03:18:10 +0900 JST] 9f732da00641498f383779b58168b5e84aa21b5130bd7b9ed196220dea6d428b: (from centos:centos7) destroy
何も引数を付けなければ実行以降のイベントが、--since=
という引数を付けた場合は指定した日時以降のイベントが出力されます。
docker events
コマンドのフォーマットはあまり機械処理には向いていませんが、頑張ればシェルスクリプトでも処理できます。
とりあえずコンセプトを実証したい場合は、以下のようなシェルスクリプトでさくっと作ってしまうとよいと思います。
#!/bin/bash docker events "$@" | while read line; do container_id="$(echo $line | sed -e 's/^.*] \(\w*\): .*$/\1/g')" event="$(echo $line | sed -e 's/^.* \(\w*\)$/\1/g')" case "$event" in start) container_name="$(docker inspect -f '{{.Name}}' "$container_id" 2> /dev/null)" container_ip="$(docker inspect -f '{{.NetworkSettings.IPAddress}}' "$container_id" 2> /dev/null)" echo "$container_id: started as $container_name at $container_ip";; die | kill) echo "$container_id: stopped";; destroy) echo "$container_id: removed";; esac done
Remote APIにアクセスする
Docker Remote APIの Monitor Docker's events でイベントを取得できます。
Node.jsで動作するDocker Remote APIライブラリのdockerodeを使った例を以下に示します。
# app.coffee Docker = require 'dockerode' JSONStream = require 'JSONStream' docker = new Docker socketPath: '/var/run/docker.sock' docker.getEvents {}, (error, stream) -> throw error if error stream?.pipe JSONStream.parse().on 'root', (event) -> switch event.status when 'start' console.info "#{event.time}: #{event.status}: #{event.id} from #{event.from}" when 'die', 'kill' console.info "#{event.time}: #{event.status}: #{event.id} from #{event.from}" when 'destroy' console.info "#{event.time}: #{event.status}: #{event.id} from #{event.from}"
dockerodeのAPIは非同期になっており、コールバックで結果が返ってきます。
getEvents
のコールバックの中でinspect()
を実行すればコンテナ名などの詳細情報を取得できます。
slack-docker ではdockerodeで取得したイベントをSlackに連携しています。 参考になれば幸いです。