【Docker】localロギングドライバーってなんだ?
Dockerのログ設定を調べていて気になるオプションを見つけた。オーバヘッドを最小にするとか書いてある。みたいな話
スポンサーリンク
ちなみにこのページに記載している情報は商売として客共にサービスを提供しているサーバーで実用に耐えうる物かは分からないので、その辺は自己責任でどうぞ。
localロギングドライバー
Dockerのログ設定を調べていて気になるオプションを見つけた。
Dockerのロギングドライバーはデフォルトだとjson-file
になっている。他にもsyslog
とかfluentd
とかあるのは知っているのだが、local
という初耳なドライバーがある。
公式ドキュメントの説明には次のように書かれている。
Logs are stored in a custom format designed for minimal overhead.
(ログはオーバーヘッドを最小にするために設計されたカスタムフォーマットで保存されます)
パフォーマンスが高いとかそういう謳い文句に非常に弱いケチ人間としては気になる設定。
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
で使えるlabels
、env
、env-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
が使えるロギングドライバーはlocal
、json-file
、journald
の3つ。という具合。
要するにdocker logs
は使えるので、json-file
を使っていた人は今まで通りの使い方で使える、ということ。
ログファイルの場所
docker inspect
のLogPath
は空になる。
ドキュメントには「将来バージョンで実装が変更される可能性があるので外部ツールで使用するな」みたいなことが書かれてあるので、そういう事だと思う。
ログファイルを直接読みに行くタイプのツールを使っている人は使えない。そんなツールがあるかは別として。
で、実際のログファイルはどこか?というと、/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-opt
にmode=non-blocking
を指定するとログがノンブロッキングで書き込まれるようになる。
もちろんdaemon.json
に指定してもいい。
{
"log-opts": {
"mode": "non-blocking"
}
}
これは、出力されたログをリングバッファ(メモリ)に書き込んだ後でディスクに出力するというもの。そのためアプリケーション側のログ出力がIO待ちで待たされることがなくなる。
リングバッファなのでノンブロッキングでも順番がぐちゃぐちゃになることはないと思うが、一度に大量の出力を行うとバッファが溢れる(まだディスクに書き出されてない古いログが捨てられる)可能性はある。
リングバッファとして割り当てるメモリ量は--log-opt
にmax-buffer-size
を指定する、デフォルトは1m。
そもそもログ出力がボトルネックになるほどのサービスを生み出す方が難しいと思うが、覚えておくといつか役に立つかもしれない。