読者です 読者をやめる 読者になる 読者になる

Carpe Diem

備忘録。https://github.com/jun06t

dockerのlog周りの対応

概要

dockerを本番運用する際にログの扱いに悩んだので情報をまとめてみました。

環境

  • docker v1.12.1

コンテナのログは何処に渡すべきか

主に以下の3通りになると思います。

  1. コンテナ内に保存
  2. volume先に指定してに永続保存
  3. log driverを使って転送

a. コンテナ内に保存

何も設定しないとコンテナに保持されます。

メリット

何も設定しなくていい

デメリット

当然コンテナが破棄された場合はログファイルがなくなります。


b. volume先に指定してに永続保存

volumeを用いてホストに永続的に保存します。
参照が切れないように-v <host_path>:<container_path>とするか、--volumes-from <container_name>でデータ用コンテナに保持してください。

メリット

コンテナを破棄したとしてもvolumeでそこを指定すれば継続して利用ができます。

デメリット

オートスケール等でインスタンス自体も頻繁に作成・破棄される場合は別のところに転送して保持する必要があります。

その場合は別途fluentdコンテナなどを用意&そのvolumeをマウントして転送することになると思います。


c. log driverを使って転送

Configure logging drivers - Docker

fluentdawslogsgcplogsなどのdriverを用いて別のところに転送します。

メリット

コンテナを破棄しても大丈夫ですし、オートスケールでインスタンスが破棄されても大丈夫です。

デメリット

fluentdを例に挙げると、ログの切り分けが大変です。

例えばアクセスログ・行動ログ・課金ログなど、複数のログファイルに分けていた場合、これらのドライバーはログを分けて転送することができません。
なのでこの方針で進める場合はログ自身に判別するためのタグをもたせ、fluentdのout_rewrite_tag_filterなどを使って分ける必要があります。

elasticsearch - Docker logs, stderr - Stack Overflow

docker logsに標準コンソール以外のログを表示するにはどうすればいいか

nginxのように/dev/stdout/dev/stderrへログファイルをリンクすれば良いです。

github.com

ln -sf /dev/stdout /var/log/nginx/access.log
ln -sf /dev/stderr /var/log/nginx/error.log

rotationはどうすべきか

ログの悩みどころはインスタンスの容量を圧迫する点です。
特に膨大なアクセスが有る場合はきちんとrotateして圧縮or破棄しないと容量が枯渇します。


a. コンテナ内に保存

コンテナが頻繁に破棄されたらなくなるのでそもそも不要です。


b. volume先に指定してに永続保存

christina04.hatenablog.com

のようにlogrotateを使ってrotateする形になると思います。


c. log driverを使って転送

awslogsfluendの場合、そちらに転送されるのでrotateは考えなくて大丈夫です。

syslogの場合、一般的なLinuxシステムであれば元々ホスト側でlogrotateが動いているので4週間分でrotateされます。

デフォルトのjson-fileの場合、ホスト側に実ファイルとして保存されるのでrotateを考える必要があります。

これをrotateしたい場合、

https://docs.docker.com/compose/compose-file/#/logging

こちらのcomposeの設定のオプションを使って、

logging:
  driver: "json-file"
  options:
    max-size: "10m"
    max-file: "100"

のように設定することでrotateしてくれるようになります。
ただしこのlogはコンテナを破棄すると消えるので、コンテナの再作成が頻繁であればaと同じで対応は不要です。

その他

awslogsがDocker for Macで使えない

awslogsを使う場合、AWSのCredentialsが必要ですがDocker for Macだとdocker daemonにその環境変数を渡すことができないので(clientは当然できますが、awslogsはdaemon側で処理するのでdaemon側に必要)ローカルから転送することはできませんでした。

github.com


rotationが面倒だからpm2のログをstdoutだけにしたい

pm2のログはデフォルトでは/home/user/.pm2/logsに保存されます。これはrotateされないので、rotationを面倒だと思う場合は

    "error_file"  : "/dev/null",
    "out_file"    : "/dev/null",

と設定することでstdoutだけにできます。あとはstdoutがdocker logsの方に流れるのでそれをawslogsなどに転送すればrotationを考えずに済みます。

github.com


docker logsの実ファイルってどこ

json-fileの場合、ホスト側に実ファイル(docker logsで参照するファイル)あります。これはコンテナパス(/var/lib/docker/containers/)の各コンテナのディレクトリにあります。

docker - Where is a log file with logs from a container? - Stack Overflow

まとめ

本番で動かす場合は以下の2通りがベスト・プラクティスかなと考えています。

ログの種類が1つで済む場合

docker log driverでfluentdやマネージドなサービスに転送。


ログの種類が複数ある場合(ファイル自体が複数)

volumeでホスト側にログファイルを保持し、fluentdで各ログファイルをtailして転送。
rotationに関してはlogrotateやログライブラリ側で対応する。