2017年3月8日水曜日

コンテナの標準出力をログファイルに落としホストマシンで確認する方法

概要

どういうことかというとコンテナ上で動作しているバイナリファイルもしくはコマンドがあるとします
そのコマンドは結果を標準出力に吐くとします
標準出力なのでログファイルには残りません

そんな場合にログファイルに出力させかつホストマシン側でも確認できる方法を紹介します

環境

  • Mac OS X 10.12.3
  • Docker 1.13.1

標準出力するコマンドの作成

適当で OK です
このファイルをコンテナ上で動作させます

  • vim cat echo_loop.sh
#!/bin/sh

while :
do
  echo `date`
  sleep 1
done

Dockerfile の作成

コンテナとして動作させるためイメージを作成します
イメージには上記のコマンドがインストールされるようにします

  • Dockerfile
FROM alpine:latest

COPY ./echo_loop.sh /bin
RUN chmod 755 /bin/echo_loop.sh

CMD ["/bin/sh", "-c", "/bin/echo_loop.sh >> /var/log/echo_loop.log 2>&1"]

イメージの作成とコンテナの起動

ビルドしてできたイメージからとりあえずコンテナを起動します

  • docker build -t myalpine .
  • docker run -d myalpine

でコンテナが起動したら exec して /var/log/echo_loop.log に標準出力がリダイレクトされているか確認します

ホストマシンでも見えるようにする

コンテナを起動する時にマウントオプション -v を指定します

  • mkdir log
  • cd log
  • docker run -d -v $(pwd):/var/log/ myalpine

これでホストマシン側にも echo_loop.log が出力されるようになります

おまけ: ローテーションの挙動を確認する

Mac なので newsyslog を使います

  • cd etc/newsyslog.d
  • sudo vim echo_loop.conf
# logfilename                        [owner:group]     mode count size when flags [/pid_file] [sig_num]
/Users/hawksnowlog/log/echo_loop.log hawksnowlog:staff 644  5     10   *    J

一応設定ファイルの説明をすると

  • owner:group・・・hawksnowlog:staff
  • mode 「644」・・・ローテーション後のファイルの権限を 644 にする
  • count 「5」・・・ 5 世代分残す
  • size 「10」・・・10KB 以上だったらローテーションする、「*」の場合はサイズを使わない
  • when 「*」・・・時間でローテーションしない、「$D0」の場合は毎日 0 時にローテーション
  • flag 「J」・・・bz 圧縮する

ポイントってわけではないですが、他のローテーションツールを使う場合でも権限回りは気をつけてください
ローテーション後に root 権限のファイルになるとコンテナから書き込めなくなります
作成したらローテーションしてみます

  • sudo newsyslog -f /etc/newsyslog.d/echo_loop.conf

ログを tail などで見ていると Mar 2 13:07:12 host newsyslog[6655]: logfile turned over due to size>1K というログがでればローテーション成功です
echo_loop.log.0.bz2 という名前のファイルが新しく出来ていると思います
が、ローテーションした echo_loop.log にはログが出力されません

おそらくコンテナ側に kill シグナルを送信しないといけないのが原因だと思います
logrotate の copytruncate なら問題なく出力されると思います (すいません、試せていません)
https://github.com/docker/docker/issues/7333

当然ですが、コンテナを再起動すればログは問題なく出力を再開します

最後に

コンテナ内で動作しているプロセスの標準出力をホスト側で確認する方法を紹介しました
ローテーション回りがまだ解決していませんが logrotate を使えばいけると思います
わざわざマウントしなくても docker にある log drivers を使えばもっと簡単に管理できると思います
log drivers は別途検証したいなと思っています

参考サイト

0 件のコメント:

コメントを投稿