言語を切り替える
テーマを切り替える

Dockerログ管理実践:ドライバー設定から一元化収集まで

深夜2時、スマホが震えました。本番サーバーのディスク容量警告です。閾値は85%。

ベッドから起きてノートPCを開き、SSHでログインしました。心拍数が少し上がります。df -hで確認すると、ルートパーティションの空き容量はわずか12%。原因を調べていくと、/var/lib/docker/containersの中に犯人がいました——2週間稼働していたNginxコンテナのログファイルが、すでに12GBまで膨れ上がっていたのです。

正直なところ、かなり参りました。Dockerはデフォルトでログサイズを制限しないため、この点を知らない人は多いのです。そのコンテナは毎日数万件のアクセスログを出力し、json-fileドライバーが忠実にすべて記録していたため、わずか2週間でディスクを満杯にしてしまったのです。

結局、そのログファイルを削除し、すべてのコンテナにローテーション設定を追加しました。この作業は深夜4時までかかりました。

その夜以来、1週間かけてDockerログ管理について体系的に整理しました——ログドライバーの選択、ローテーションパラメータの設定、マルチコンテナ環境での一元化収集ソリューションまで。この記事はその時の経験から得た教訓をまとめたもので、皆さんが同じ失敗を避ける一助になれば幸いです。

一、Dockerログドライバーの全体像

まず基本的な概念を押さえておきましょう。Dockerコンテナのログは、ただ書き込まれるわけではありません。「ログドライバー(Logging Driver)」を通じて、ログの保存先や方法が決まります。

Dockerは複数のログドライバーをサポートしており、それぞれ適用シーンが異なります。コンテナを実行すると、Dockerはデフォルトでjson-fileドライバーを使用します——これはstdoutとstderrの内容をJSON形式でローカルファイルに書き込むものです。このファイルは/var/lib/docker/containers/<コンテナID>/<コンテナID>-json.logに保存されます。

json-fileのメリットはシンプルさです。追加設定が不要で、ログ形式が統一されており、Dockerコマンド(docker logs)で直接読み取れます。しかし、明らかな落とし穴もあります:デフォルトではサイズ制限がありません。コンテナが稼働し続ける限り、ログも蓄積され続け、最終的にはディスクを圧迫します。

以下の表は、6つの主要なドライバーをまとめたものです:

ドライバー適用シーン構造化サポート外部サービス依存パフォーマンス影響
json-file開発・デバッグ、単一サーバーあり(自動JSON)なし
syslog既存のsyslog基盤がある企業なし(解析必要)あり(rsyslog)
journaldsystemd環境一部なし
fluentdクラウドネイティブ監視スタック、ログ一元収集あり(カスタムタグ)あり(Fluentdサービス)
gelfGraylogログプラットフォームユーザーありあり(Graylog)
noneログ無効化、一時コンテナなしなしなし

json-fileとsyslogは最も一般的な選択肢です。json-fileはローカルデバッグや軽量なデプロイに適しています。syslogは既存のsyslog基盤がある企業に適しており、ログを直接rsyslogやsyslog-ngに送信し、集中ログシステムで一元管理できます。

journaldドライバーはログをsystemd journalに渡します。サーバーでsystemdを使用している場合(ほとんどの現代的なLinuxディストリビューション)、journaldは便利な選択肢で、journalctlコマンドでログを確認できます。

fluentdとgelfは集中ログ収集向けのドライバーです。fluentdはElasticsearch、Kafka、クラウドストレージなど様々なバックエンドにログを送信できます。gelfはGraylogプラットフォームの専用形式です。これら2つのドライバーはマルチコンテナクラスタ環境に適していますが、別途ログ収集サービスのデプロイが必要です。

noneドライバーはログを完全に無効化します。一部の一時コンテナやバッチ処理タスクでは、ログが重要でない場合、noneを使用することでリソースを節約できます。

選び方は?

単一サーバーデプロイ、開発・デバッグ:json-fileで十分です。ただし、ローテーションパラメータを追加することを忘れないでください(次のセクションで説明)。企業にsyslogがある場合:syslogを使用し、既存のインフラを活用します。コンテナクラスタ、ログを一元管理する必要がある場合:fluentdまたはLoki(後で詳しく説明)。一時コンテナ、ログが不要:直接noneを使用します。

二、ログローテーション設定の実践

冒頭の問題に戻りましょう:ログファイルが12GBまで膨れ上がりました。どう防げばいいでしょうか?ローテーションパラメータを追加することです。

json-fileドライバーは3つの重要なパラメータをサポートしています:

  • max-size:単一ログファイルの最大容量。この値を超えると、Dockerは新しいファイルを作成し、古いファイルの番号を増やします。例えばmax-size=10mの場合、単一ファイルは最大10MBです。
  • max-file:保持する履歴ファイル数。この数を超えると、最も古いファイルが削除されます。例えばmax-file=3の場合、最大3つの履歴ファイルと1つの現在ファイルを保持します。
  • compress:ローテーション後の古いファイルを圧縮するかどうか。デフォルトはfalse。trueに設定するとディスク容量を節約できますが、CPUのオーバーヘッドが若干増加します。

これら3つのパラメータの組み合わせで、ログのディスク使用量を効果的に制御できます。例えばmax-size=10m, max-file=3の場合、ログは最大30MBを占有します(圧縮すればさらに小さくなります)。

設定方法:グローバル vs コンテナ個別

Dockerログローテーションは3つのレベルで設定できます:

1. グローバル設定(daemon.json)

すべてのコンテナに適用され、一度設定すれば完了です。/etc/docker/daemon.jsonに追加します:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3",
    "compress": "true"
  }
}

変更後、Dockerデーモンを再起動します:sudo systemctl restart docker。これで新しく作成されるすべてのコンテナがこの設定を継承します。

注意:グローバル設定は新規作成のコンテナにのみ適用されます。既存のコンテナは個別に処理するか、削除して再作成する必要があります。

2. コンテナ個別設定(docker run)

特定のコンテナに個別にパラメータを設定する場合:

docker run -d \
  --name nginx \
  --log-driver json-file \
  --log-opt max-size=50m \
  --log-opt max-file=5 \
  --log-opt compress=true \
  nginx:alpine

高トラフィックアプリケーションでは、パラメータを緩和できます。例えばmax-size=50m, max-file=10で、より大きなログ容量を許可します。

3. Docker Compose設定

これが最も一般的な方法で、本番デプロイでは基本的にComposeを使用します:

version: "3.9"
services:
  webapp:
    image: webapp:latest
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
        compress: "true"

  nginx:
    image: nginx:alpine
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "5"

各サービスで個別に設定でき、柔軟性が高いです。

本番環境の推奨値

SigNozの2024年実践ガイドでは、以下の推奨値が提示されています:

  • 開発・テスト環境max-size=10m, max-file=3、必要十分です。
  • 中程度トラフィックアプリmax-size=50m, max-file=5、トラブルシューティングのためにより多くの履歴ログを保持。
  • 高トラフィックアプリmax-size=100m, max-file=10、ログローテーションが早すぎて履歴が失われるのを防ぐ。

正直なところ、具体的な値はビジネスシーンによります。重要な原則は、ディスク容量とログの重要性に基づいてバランスを見つけることです。ディスクが大きく、ログが重要——より多く保持。ディスクが限られていて、ログが重要でない——より厳しく制限。

三、一元化ログ収集ソリューションの比較

単一サーバー環境ではログローテーションで十分です。しかし、十数個、数十個のコンテナがある場合、ログが各サーバーに分散していると、問題の調査が非常に困難になります——各サーバーにログインして、docker logsで1つずつ確認する必要があります。

一元化ログ収集はこの問題を解決します:すべてのコンテナのログを1箇所に集約し、統一的に保存・検索します。

現在、主流のソリューションは3つあります:

ELK Stack(Elasticsearch + Logstash + Kibana)

ELKは長年存在する古典的なソリューションです。Logstashがログを収集し、Elasticsearchが保存・インデックス作成を行い、Kibanaが視覚的なクエリインターフェースを提供します。

メリットは強力な機能です——全文検索、複雑なクエリ、視覚化チャート、成熟したエコシステム。デメリットも明確です:リソース消費が高い。Elasticsearch自体が重量級サービスで、メモリ使用量は頻繁に数GBに達します。Logstashも軽量ではなく、設定が複雑で学習コストが高いです。

専門の運用チームがあり、ログ量が多く、複雑なクエリが必要な大企業に適しています。

EFK(FluentdがLogstashを置換)

EFKはELKの派生形で、LogstashをFluentdに置き換えたものです。Fluentdはより軽量で、メモリ使用量は数百MB、プラグインエコシステムが豊富で、多様な入出力ソースをサポートしています。

設定はLogstashより簡潔ですが、Elasticsearchの重量は変わりません。全体的なリソース消費は依然として高く、中規模〜大規模チームに適しています。

Loki + Promtail + Grafana

LokiはGrafana Labsが開発したログシステムで、設計思想がユニークです:全文インデックスを作成せず、ログのラベル(コンテナ名、アプリケーション名など)のみをインデックス化します。ログ内容は圧縮ファイルに保存されます。クエリ時はgrep方式でマッチングし、パフォーマンスは十分です。

この設計により、Lokiは極めて軽量です——メモリ使用量は数百MB、ストレージコストはElasticsearchよりはるかに低いです。PromtailはLoki専用の収集エージェントで、設定は簡単です。Grafanaがクエリインターフェースとなり、Lokiとシームレスに統合されます。

クラウドネイティブ環境、特にKubernetesに適しています。小規模チーム、予算が限られている場合、Lokiはコストパフォーマンスの高い選択肢です。

ソリューション比較表

ソリューションメリットデメリット適用規模コスト
ELK機能が強力、クエリが柔軟、エコシステムが成熟リソース消費が高い、設定が複雑、ストレージコストが高い大企業
EFKFluentdが軽量、プラグインが豊富Elasticsearchが依然として重い、設定が依然として複雑中〜大規模中〜高
Loki極めて軽量、低コスト、クラウドネイティブと親和性が高いクエリ機能が弱い、全文検索に不向き小規模/K8s

選び方は?

簡単なアドバイスをします:

  • 小規模チーム(10人以下)、予算が限られている:Loki。デプロイが簡単、リソース消費が低い、Grafanaのインターフェースが使いやすい。
  • 中規模チーム(10-50人)、ある程度の運用能力:LokiまたはEFK、ログ量による。
  • 大企業、専門の運用チーム:ELK。機能が充実、エコシステムが成熟、投資に値する。

すでにGrafanaを監視に使用している場合、Lokiはほぼ天然の選択です——同じインターフェースでメトリクスとログを確認でき、体験がスムーズです。

四、本番環境での落とし穴回避ガイド

最後の章では、私が経験したいくつかの落とし穴を紹介し、注意喚起します。

1. ローテーション設定忘れ、ディスク満杯

これが最も一般的な落とし穴です。多くの人はコンテナをデプロイする際、ログローテーションを全く考えていません。数ヶ月後にディスク警告が出て、調べてみるとログファイルが数十GBになっていることがわかります。

推奨:Docker daemon.jsonでグローバルデフォルト値を設定し、新規コンテナが自動的に継承するようにします。毎回docker runでパラメータを追加することを期待しないでください——人は忘れますが、設定は忘れません。

2. コンテナ再起動でログ消失

json-fileドライバーには特性があります:コンテナ削除後、ログファイルも一緒に削除されます。コンテナを再起動する際、docker restartではなくdocker rm + docker runを使用すると、ログは消えてしまいます。

これは履歴問題の調査に隠れたリスクがあります。例えば、あるコンテナが深夜にクラッシュして再起動した場合、クラッシュ前のログを確認したいけれど、コンテナはすでに再作成され、ログは消えてしまったという状況です。

推奨

  • コンテナを再起動する際はdocker restartを使用し、削除して再作成しない。
  • 重要なアプリケーションのログは、fluentdまたはsyslogドライバーを使用して外部ストトレージに送信し、コンテナ削除によるログ消失を防ぐ。
  • 重要なログファイルは定期的にバックアップする(特に本番環境)。

3. Fluentdアドレス設定ミス

fluentdドライバーを使用する際、ログはTCPでFluentdサービスに送信されます。Fluentdアドレスが間違っていると、コンテナ起動時にエラーが出ませんが、ログは収集されません——ログは集中ストレージにあると思い込んでいるが、実際は転送中に失われています。

設定例:

docker run -d \
  --log-driver fluentd \
  --log-opt fluentd-address=127.0.0.1:24224 \
  --log-opt tag="docker.{{.Name}}" \
  my-web-app

fluentd-addressはFluentdサービスが実際にリッスンしているアドレスと一致させる必要があります。ポートはデフォルトで24224、TCPプロトコルです。

トラブルシューティング方法

  • まずFluentdサービスが正常に稼働しているか確認:curl http://localhost:24224またはnetstat -tlnp | grep 24224
  • docker inspect <コンテナID>でログドライバー設定が正しいか確認。
  • FluentdログでDockerから送信されたログストリームを受信しているか確認。

4. モニタリングとアラート

ログ管理は設定したら終わりではありません。モニタリングも必要です。

2つの重要な指標

  • ディスク容量:定期的に/var/lib/docker/containersディレクトリのサイズを確認。アラート閾値を設定(例:10GBを超えたら通知)。
  • ログ遅延:一元収集シナリオでは、FluentdまたはLokiの書き込み遅延をモニタリング。遅延が高すぎる場合はネットワーク問題またはストレージのボトルネックの可能性があります。

Prometheus + Grafanaでモニタリングできます。あるいは、よりシンプルに——スクリプトを書いて定期的にチェックし、Cronで実行する方法もあります。

まとめ

この記事では、Dockerログ管理のいくつかの重要なポイントを説明しました:

  1. ログドライバーの選択:json-fileが最も汎用的、syslogは企業インフラに適している、fluentdは一元収集用。
  2. ログローテーション設定max-size + max-fileの組み合わせ、グローバル設定で安心、コンテナ個別設定で柔軟。
  3. 一元収集ソリューション:小規模チームはLoki、大企業はELK、規模と予算による。
  4. 落とし穴回避ガイド:グローバルデフォルトローテーション、ログ消失防止、Fluentdアドレス確認、ディスク容量モニタリング。

最後にクイック設定テンプレートを提示します:

// /etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3",
    "compress": "true"
  }
}

アクションプラン:まだログローテーションを設定していないなら、今すぐ確認してください。/var/lib/docker/containersディレクトリに巨大なログファイルがないか確認し、daemon.jsonにローテーションパラメータを追加し、Dockerデーモンを再起動してください。数分の作業で、深夜2時にディスク警告の対応を迫られるトラブルを防げます。

Dockerログローテーション設定

Dockerコンテナのログローテーションを設定し、ログファイルによるディスク容量枯渇を防ぐ

⏱️ 目安時間: 10 分

  1. 1

    ステップ1: 現在のログ状態を確認

    以下のコマンドを実行して、コンテナログの使用状況を確認します:

    ```bash
    # ログディレクトリの総サイズを確認
    du -sh /var/lib/docker/containers

    # 各コンテナのログサイズを確認
    docker ps -q | xargs -I {} sh -c 'echo -n "{}: "; docker inspect --format="{{.LogPath}}" {} | xargs du -sh 2>/dev/null || echo "N/A"'
    ```

    あるコンテナのログが1GBを超えている場合、ローテーション設定が必要です。
  2. 2

    ステップ2: グローバルデフォルトローテーションを設定

    `/etc/docker/daemon.json`を編集し、ログドライバー設定を追加します:

    ```json
    {
    "log-driver": "json-file",
    "log-opts": {
    "max-size": "10m",
    "max-file": "3",
    "compress": "true"
    }
    }
    ```

    パラメータの説明:
    - max-size: 単一ファイル最大10MB
    - max-file: 3つの履歴ファイルを保持
    - compress: 古いファイルを圧縮して容量を節約
  3. 3

    ステップ3: Dockerを再起動して設定を反映

    再起動コマンドを実行して設定を有効にします:

    ```bash
    sudo systemctl restart docker
    ```

    **注意**:グローバル設定は新規コンテナにのみ適用されます。既存のコンテナは再作成または個別設定が必要です。
  4. 4

    ステップ4: 設定を検証

    テストコンテナを作成して設定が反映されているか確認します:

    ```bash
    # テストコンテナを作成
    docker run -d --name test-nginx nginx:alpine

    # ログ設定を確認
    docker inspect --format='{{.HostConfig.LogConfig}}' test-nginx
    ```

    出力に`max-size=10m,max-file=3`パラメータが表示されるはずです。
  5. 5

    ステップ5: 古いコンテナログをクリーンアップ(オプション)

    既存のコンテナのログが大きすぎる場合、手動でクリーンアップできます:

    ```bash
    # 方法1:ログファイルを空にする(コンテナを再起動しない)
    sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' コンテナ名)

    # 方法2:コンテナを再作成(推奨)
    docker rm -f コンテナ名
    docker run ... # ログパラメータを付けて再作成
    ```

    再作成後、新しいコンテナはグローバル設定を継承します。

FAQ

Dockerのデフォルトログドライバーは何ですか?なぜサイズ制限がないのですか?
Dockerはデフォルトでjson-fileドライバーを使用し、コンテナのstdoutとstderrをJSON形式でローカルファイルに書き込みます。デフォルトでサイズ制限がないのは、ログの完全性を保証し、トラブルシューティング情報の損失を防ぐためです。しかし、これにより長期間稼働するコンテナのログが無限に増加するため、ローテーションパラメータの手動設定が必須です。
max-sizeとmax-fileパラメータの最適な組み合わせは?
推奨組み合わせ:開発環境`max-size=10m, max-file=3`(合計30MB)、本番環境`max-size=50m, max-file=5`(合計250MB)、高トラフィックアプリ`max-size=100m, max-file=10`(合計1GB)。重要なのは、ディスク容量とトラブルシューティングニーズのバランスを見つけることです。
コンテナ削除後もログは残りますか?永続化するには?
json-fileドライバーの場合、コンテナ削除時、ログファイルも一緒に削除されます。永続化ソリューション:1)fluentd/syslogドライバーを使用して外部ストレージに送信;2)`/var/lib/docker/containers`ディレクトリを定期的にバックアップ;3)コンテナ再起動時に削除して再作成ではなく`docker restart`を使用。
ELKとLokiのどちらを選ぶべき?小規模チームに適しているのは?
小規模チーム(10人以下)にはLokiを推奨:デプロイが簡単、メモリ使用量は数百MBのみ、ストレージコストが低い、Grafanaとシームレスに統合。ELKは機能が強力ですがリソース消費が高く(Elasticsearchのメモリは頻繁に数GB)、専門の運用チームがある大企業に適しています。すでにGrafanaを監視に使用している場合、Lokiは天然の選択です。
Fluentdアドレス設定ミスで何が起こる?どうトラブルシューティングする?
アドレス設定ミスの場合、コンテナは正常に起動しますがログは収集されず、トラブルシューティング時にログ消失に気づきます。トラブルシューティング手順:1)Fluentdサービスの稼働状態を確認`netstat -tlnp | grep 24224`;2)コンテナのログ設定を確認`docker inspect --format='{{.HostConfig.LogConfig}}' コンテナID`;3)FluentdログでDockerからのデータストリームを受信しているか確認。
既存のコンテナに新しいログローテーション設定を適用するには?
グローバル設定`daemon.json`は新規コンテナにのみ適用されます。既存コンテナの処理方法:1)コンテナ再作成(推奨):`docker rm -f コンテナ名`後、新しい設定で再作成;2)コンテナ個別設定:`docker update --log-opt max-size=10m コンテナ名`(一部パラメータはホットアップデート対応);3)ログの手動削除:`truncate -s 0 $(docker inspect --format='{{.LogPath}}' コンテナ名)`。
Dockerログのディスク使用量をモニタリングするには?
モニタリングソリューション:1)シンプルスクリプト + Cron:定期的に`du -sh /var/lib/docker/containers`を実行、閾値超過でアラート送信;2)Prometheus + node_exporter:ディスク使用率をモニタリング;3)ログシステムの組み込みモニタリング:Loki/Fluentdは書き込み遅延指標を提供。ディスクアラート閾値(例:10GB超過で通知)を設定し、深夜の対応を避けることを推奨。

6 min read · 公開日: 2026年4月30日 · 更新日: 2026年5月13日

関連記事

コメント

GitHubアカウントでログインしてコメントできます