なうびるどいんぐ

脳みそ常時-3dB

【Docker】localロギングドライバーってなんだ?

      HimaJyun

Dockerのログ設定を調べていて気になるオプションを見つけた。オーバヘッドを最小にするとか書いてある。みたいな話

スポンサーリンク

ちなみにこのページに記載している情報は商売として客共にサービスを提供しているサーバーで実用に耐えうる物かは分からないので、その辺は自己責任でどうぞ。

localロギングドライバー

Dockerのログ設定を調べていて気になるオプションを見つけた。

Dockerのロギングドライバーはデフォルトだとjson-fileになっている。他にもsyslogとかfluentdとかあるのは知っているのだが、localという初耳なドライバーがある。

公式ドキュメントの説明には次のように書かれている。

Logs are stored in a custom format designed for minimal overhead.
(ログはオーバーヘッドを最小にするために設計されたカスタムフォーマットで保存されます)

Configure logging drivers | Docker Documentation

パフォーマンスが高いとかそういう謳い文句に非常に弱いケチ人間としては気になる設定。

localってなんだ?

上で引用した通り、パフォーマンスとディスク効率がより高いロギングドライバー。

追加されたのはバージョン18.09.0、該当のプルリクエストはmoby/moby#37092、ソースコードはdaemon/logger/local

内容としては、ログをバイナリで書き込んでいる模様。なのでcatとかで直接ログファイルを見ることは出来ない。

jsonの処理とか誰がどう考えても重い部類に入るだろうし、処理しやすいファイル形式で扱う事によりログが原因でのパフォーマンス劣化を防ぐ狙いがあるっぽい。

ログ出力がボトルネックになることは珍しいと思うけど、秒間アクセス数が高いWebサーバーとかだとあり得ないとも言い切れない。

使い方

ログドライバーにlocalを指定する。それだけ。

docker run --log-driver local alpine echo hello world

daemon.jsonで指定する場合はこんな感じ。

{
    "log-driver": "local"
}

jsonって手で書くと色々しんどいよね~、末尾カンマとか(小声

オプション

オプションはmax-size(デフォルト: 20m)、max-file(デフォルト: 5)、compress(デフォルト: true)の3つが使える。

json-fileで使えるlabelsenvenv-regex辺りは非対応。

デフォルトでログローテーションが設定されているので、json-fileでありがちな「何も設定せずに使ってたらログが肥大化」なんてことは起きない。

ちなみにdaemon.jsonで指定する場合はすべて文字列として指定する必要があるので要注意。

{
    "log-driver": "local",
    "log-opts": {
        "max-size": "20m",
        "max-file": "5",
        "compress": "true"
    }
}

jsonって手で書くと色々(ry

docker logsは使える

「catとかで直接ログファイルを見ることは出来ない」とは書いたが、そんな使い方をしている奴が実際に居るのか?ってのは微妙な所。

Dockerのコンテナログはdocker logsを使う。localロギングドライバーでもこれでログを確認できる。

なので、2019/09/05の時点でdocker logsが使えるロギングドライバーはlocaljson-filejournaldの3つ。という具合。

要するにdocker logsは使えるので、json-fileを使っていた人は今まで通りの使い方で使える、ということ。

ログファイルの場所

docker inspectLogPathは空になる。

ドキュメントには「将来バージョンで実装が変更される可能性があるので外部ツールで使用するな」みたいなことが書かれてあるので、そういう事だと思う。

ログファイルを直接読みに行くタイプのツールを使っている人は使えない。そんなツールがあるかは別として。

で、実際のログファイルはどこか?というと、/var/lib/docker/containers/<コンテナID>/local-logs/に出力されている。

もちろんバイナリなので直接読むことは出来ない。docker logsを使おう。

どういう人向けか?

現在json-fileを利用中でjson-file固有の機能を使っていない人、要するにデフォルトのまま使っている人とかはlocalに切り替えちゃって良いんじゃないかと思う。

そもそも、ログがjsonで出力されたとしてもj s o n と し て 利 用 し た こ と な いって人は少なくないのでは?

直接ファイルをパースしてどうこう……なんて使い方は珍しい気がする。docker logs使えばいいだけだし。

という訳なので、おうちサーバーのDockerはlocalに切り替えてみた。

せっかく失敗しても怒られない環境があるのに、色々試さないなんて損だし。

ついでにnon-blocking

--log-optmode=non-blockingを指定するとログがノンブロッキングで書き込まれるようになる。

もちろんdaemon.jsonに指定してもいい。

{
    "log-opts": {
        "mode": "non-blocking"
    }
}

これは、出力されたログをリングバッファ(メモリ)に書き込んだ後でディスクに出力するというもの。そのためアプリケーション側のログ出力がIO待ちで待たされることがなくなる。

リングバッファなのでノンブロッキングでも順番がぐちゃぐちゃになることはないと思うが、一度に大量の出力を行うとバッファが溢れる(まだディスクに書き出されてない古いログが捨てられる)可能性はある。

リングバッファとして割り当てるメモリ量は--log-optmax-buffer-sizeを指定する、デフォルトは1m。

そもそもログ出力がボトルネックになるほどのサービスを生み出す方が難しいと思うが、覚えておくといつか役に立つかもしれない。

 - サーバー