logspoutでDockerコンテナのログの集約・ルーティング

progrium/logspout

logspoutは,ホスト内で動かした全てのDockerコンテナの出力を集約して,好きなところに飛ばす(ルーティングする)ためのツール.開発者はDokkのJeff Lindsay

以下の2つの特徴がある

  • コンテナとして起動(ステートレス)
  • HTTP APIによるルーティングの設定

ログを貯めて管理したり,検索するといったことはできない.コンテナのログをリアルタイムで好きなところに飛ばすだけ.

これだけだが,Dockerのログの問題をいい感じに解決してくれそう.

Dockerのログのしくみ

まず,簡単にDockerのログのしくみを説明する.

現時点(2014年5月)でDockerはコンテナ内で吐き出されたstdout/stderrを取得することができる.コンテナのプロセスがstdoutstderrにログを吐き出し,Dockerはそれをホストにjsonとして保存する.docker logコマンドを使うとそれを取得することができる.

これはシンプルだけど欠点でもある.いずれディスクが圧迫されるし,毎回docker logを叩くわけにもいかない.そのため,Dockerのログをどうするかってのはいろいろ試みられている.

Dockerのログ収集の試み

Dockerコンテナのログ収集の試みは,大きく分けて3つある.

やりようはいろいろあるが,少なくともDocker的に良いのは,

  • コンテナに複数プロセスを立てない 
  • ホストに多くを設定しない

これを満たすのは,3番目の専用のコンテナを立てる方式.logspoutはこれをシンプルに実現することができる(例えば,上のように--volume-fromとか必要ない)

logsoutを使う

まず,インストール.素晴らしい.

1
$ docker pull progrium/logspout

例として,”hello world”を出力し続ける単純なコンテナを立てておく.

1
2
$ docker run -d --name hello1 busybox /bin/sh -c "while true; do echo hello world; sleep 1; done"
$ docker run -d --name hello2 busybox /bin/sh -c "while true; do echo hello world; sleep 1; done"

これらに対してログを収集するには以下を実行する.

1
$ docker run -d -p 8000:8000 --name log -v=/var/run/docker.sock:/tmp/docker.sock progrium/logspout

HTTP APIのアクセスを可能にするため8000ポートを解放し,ホストの/var/run/docker.sockをマウントする.

ログを見てみる.

1
2
3
4
5
6
7
$ curl $(docker port log 8000)/logs
             log|[martini] Started GET /logs for 172.17.42.1:50859
             hello2|hello world
             hello1|hello world
             hello2|hello world
             hello1|hello world
             hello2|hello world

リアルタイムの出力が確認できる.出力は色づけもされている.

ルーティング

一番単純な方法は,rsyslogに投げること.以下のように起動コマンドにURIを指定するだけ.

1
$ docker run -v=/var/run/docker.sock:/tmp/docker.sock progrium/logspout syslog://logs.papertrailapp.com:55555

以下のようにPOSTを使って,ルーティングの設定をすることもできる.

1
2
$ curl $(docker port log 8000)/logs -X POST \
    -d '{"source": {"filter": "db", "types": ["stderr"]}, target": {"type": "syslog", "addr": "logs.papertrailapp.com:55555"}}'

上の例では,名前がdbであるコンテナのstderrへの出力をlogs.papertrailapp.com:55555に飛ばすように設定している.addrはDNSで名前解決さえできればいいので,Consulなどのサービスディスカバリを使えば,さらなる道を開けそう.

ルーティングは以下のようにGETでデバッグしつつ設定できる.

1
2
3
4
GET /logs
GET /logs/filter:<container-name-substring>
GET /logs/id:<container-id>
GET /logs/name:<container-name>

まとめ

考慮する問題はいくつかある.

  • 若干の遅れが生じる
  • stdout/stderrだけしか取得できない(これはDockerの仕様)

まだ出たばかりなので,1つ目はすぐに解決しそう.2つ目の問題に関しては,volumeやマウントを駆使してなんとかするしかない.

それでも素晴らしい.得に良いなと思うのが,docker runですぐ使えるところ.Dockerの良さが溢れ出ている.


Full Blog →