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

Dockerログ削除の完全ガイド:json.log でディスクがあふれない 5 つの方法

クイック結論(先に止血、あとで恒久対策)

Docker ログでディスクが逼迫したとき、効果的な順序は次のとおりです。
まず truncate で止血して容量を確保し、次に max-size + max-file でローテーションを設定し、最後にコンテナを再作成して設定を反映します。
削除だけでは再発します。設定だけでは、既存コンテナはこれまでどおり肥大化します。

午前 3 時 17 分、スマホの振動で浅い眠りから引きずり出されました。

画面には刺さるような赤いアラート——「本番サーバーのディスク使用率 100%、すべてのサービスが応答停止」。心臓が冷えました。数十万ユーザー規模の EC プラットフォームで、1 分の停止がそのまま売上損失になります。

すぐ SSH で入り、df -h を実行。ルートパーティションは本当に満杯でした。調査の末、犯人は /var/lib/docker/containers/ 配下——あるコンテナの xxx-json.log82GB だったのです。

82GB
ログファイルサイズ
Source: 1 コンテナの xxx-json.log が 82GB に達し、本番サーバーのディスク使用率が 100% になった事例

コンテナは普通に動いているのに、なぜログだけこんなに?——当時は本当に戸惑いました。

後から分かったのですが、これは珍しい話ではありません。Docker はデフォルトでログファイルサイズを制限しません。stdout と stderr の出力はすべて json.log に書き込まれ、増え続け、増え続け、ディスクが満杯になるまで止まりません。

Docker ログに振り回されているなら、安心してください。この記事では、巨大ログの応急削除、再発防止のローテーション設定、自分に合うログドライバーの選び方をまとめます。私が踏んだ落とし穴もすべて書いてあるので、同じ轍を踏まないでほしいです。

なぜ Docker ログはディスクを食いつぶすのか

Docker のログ保存の仕組み

まず、Docker がログをどう扱うかから。

コンテナが console.log()System.out.println() などで stdout / stderr に出力すると、Docker はそれを JSON 形式のログファイルに書き込みます。場所は /var/lib/docker/containers/<container-id>/<container-id>-json.log です。

一見問題なさそうですが——Docker はデフォルトでログローテーションを行いません

つまりログファイルは分割も削除もされず、増え続けるだけ。1 日 1GB なら 1 週間で 7GB、1 ヶ月で 30GB。ログレベルが DEBUG など「おしゃべり」なアプリなら、さらに速く膨らみます。

ざっくり計算すると、中規模トラフィックの Web アプリが秒間 100 行、1 行平均 100 バイトのログを出す場合:

100行/秒 × 86400秒 × 100バイト ≈ 864MB/日 ≈ 25GB/月

同じ規模のコンテナが 10 個あれば、1 ヶ月もしないうちに 100GB ディスクは満杯になります。しかも控えめな見積もりです。

ハマりやすいシーン

自分と周りの経験から、特に危ないのは次のパターンです。

1. ログレベルが低すぎる

開発では DEBUG や INFO で問題なくても、本番にそのまま持ち込むと、HTTP リクエストごとに大量のデバッグ情報が出ます。ログが暴走します。

極端な例として、Node.js サービスがリクエストボディ全体(画像アップロードの base64 など)をログに書いていたケースがあります。1 リクエスト数 MB。3 日で 200GB ディスクが満杯でした。

2. ループするエラー出力

バグで無限ループし、例外とスタックトレースを吐き続けると、ログの増え方は恐ろしいです。

あるマイクロサービスは DB 接続プールの設定ミスで、毎秒数百回リトライし、毎回フルスタックを出力。3 時間で 2GB から 120GB まで膨らみ、ディスクごと落ちました。

3. 長期稼働の本番コンテナ

数ヶ月〜数年、ローテーションなしで動かし続けると、ログの累積は相当な量になります。

引き継いだプロジェクトでは、8 ヶ月稼働の Nginx コンテナのログが 150GB。docker logs も巨大ファイルを読むため、かなり重くなります。

4. 高トラフィックアプリ

アクセスが多ければログも多い。日 PV 数百万クラスでも、1 リクエスト 1 行の access ログだけで天文学的な量になります。

多くの人は気づかないまま運用し、ある日深夜にディスク満杯でシステムが落ちて、初めて Docker ログの罠に気づきます。

応急削除:すぐにディスク容量を確保する

ディスクが満杯でサービスが落ち、チャットで上司から @ が飛んできた——そんなときは慌てず、まず容量を空けましょう。

ステップ 1:犯人を特定する

どのログが大きいか知る必要があります。次を実行:

find /var/lib/docker/ -name "*.log" -exec ls -sh {} \; | sort -h -r | head -20

サイズ順に上位 20 件が表示されます。例:

82G /var/lib/docker/containers/a1b2c3d4.../a1b2c3d4...-json.log
35G /var/lib/docker/containers/e5f6g7h8.../e5f6g7h8...-json.log
12G /var/lib/docker/containers/i9j0k1l2.../i9j0k1l2...-json.log
...

最大のものの container ID(長い文字列)をメモします。

特定コンテナのログパスは次でも確認できます:

docker inspect --format='{{.LogPath}}' <container_name_or_id>

例:

docker inspect --format='{{.LogPath}}' nginx
# 出力:/var/lib/docker/containers/abc123.../abc123...-json.log

ステップ 2:安全にログを空にする

重要:いきなり rm でログファイルを削除しないでください。

私も最初は rm -f xxx-json.log を試し、Docker が混乱しました。Docker プロセスはファイルハンドルを保持したままなので、削除してもプロセスは書き込みを続け、ディスク容量は解放されません

正しいのはファイルを削除するのではなく、中身を空にすることです。

方法 1:cat で空にする

cat /dev/null > $(docker inspect --format='{{.LogPath}}' <container_id>)

空内容を書き込むので、ファイルは残りサイズは 0。Docker プロセスは影響を受けません。

nginx コンテナの例:

cat /dev/null > $(docker inspect --format='{{.LogPath}}' nginx)

方法 2:truncate(推奨)

truncate -s 0 $(docker inspect --format='{{.LogPath}}' <container_id>)

truncate はファイルを切り詰める専用コマンドです。-s 0 で 0 バイトにします。

nginx の例:

truncate -s 0 $(docker inspect --format='{{.LogPath}}' nginx)

方法 3:全コンテナのログを一括で空にする

すべてのコンテナログが巨大な場合:

sudo sh -c 'truncate -s 0 /var/lib/docker/containers/*/*-json.log'

注意:全コンテナのログが消えます。本当に緊急のときだけ。履歴が必要なら 1 つずつ削除する方が安全です。

効果を確認する

削除後、df -h でディスクを確認:

df -h /var/lib/docker/

使用率が下がっているはずです。下がらない場合は、まだ DEBUG ログを吐いている、ループエラーが続いているなど、アプリ側の問題を先に止める必要があります。

82GB のログを空にしたとき、使用率は 100% から 60% まで一気に下がり、サービスはすぐ復旧しました。ただしこれは対症療法。恒久対策としてログローテーションが必要です。

根本対策:ログローテーションを設定する

応急削除は一時しのぎです。Docker にログサイズを自動管理させ、無限増殖を止めましょう。

グローバル設定:daemon.json を編集

最も一般的な方法は、Docker のグローバル設定でローテーションを指定することです。

設定ファイル/etc/docker/daemon.json

存在しなければ作成し、次を追加:

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

各パラメータの意味:

  • max-size:1 ファイルの上限。到達すると新ファイルにローテーション
  • max-file:保持するログファイル数。超過分は最古を削除
  • compress:ローテーション後の古いログを圧縮するか

この設定なら、1 コンテナあたり最大 10MB × 3 = 30MB(圧縮前)程度です。

本番環境の推奨値

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

max-size: "100m" で調査用の履歴を多めに残し、max-file: "3" で直近 300MB 相当を保持します。

状況に応じた調整例:

  • ログ量少:max-size: "10m", max-file: "3"
  • 中程度:max-size: "50m", max-file: "3"
  • 多い:max-size: "100m", max-file: "5"

重要:値はすべて引用符付き文字列です。"max-size": 10m(引用符なし)はエラーになります。

Docker を再起動して反映

daemon.json 変更後は再起動が必要:

sudo systemctl restart docker

ただし——この設定は新規作成されるコンテナにのみ有効です。既存コンテナには効きません。再作成が必要です。

docker run の場合:

docker stop <container_name>
docker rm <container_name>
docker run [元の引数] <image>

docker-compose の場合:

docker-compose down
docker-compose up -d

down でコンテナを削除し、up -d で新設定のコンテナを作り直します。

単一コンテナ向けの設定

グローバルを変えず、特定コンテナだけ制限したい場合:

docker run

docker run -d \
  --name my-app \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  nginx:latest

docker-compose.yml

version: '3.8'
services:
  web:
    image: nginx:latest
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
        compress: "true"

コンテナごとにポリシーを分けられます。例:

  • Nginx:ログ多め → max-size: "50m", max-file: "5"
  • 軽い cron ジョブ:max-size: "5m", max-file: "2"

設定が効いているか確認

docker inspect で LogConfig を確認:

docker inspect <container_name> | grep -A 10 LogConfig

期待する出力例:

"LogConfig": {
    "Type": "json-file",
    "Config": {
        "max-file": "3",
        "max-size": "10m",
        "compress": "true"
    }
}

{} の空オブジェクトなら、まだデフォルト(無制限)です。コンテナを再作成してください。

設定後は全コンテナのログ設定をチェックする小さなスクリプトを書き、漏れがないか確認するのがおすすめです。

ログドライバー選択ガイド

ここまではデフォルトの json-file 前提でした。Docker には複数のログドライバーがあり、用途ごとに向き不向きがあります。

json-file(デフォルト)

Docker の標準選択肢です。

メリット

  • docker logs が使え、トラブルシュートが楽
  • max-sizemax-file を足すだけで設定しやすい
  • ローカル保存でアクセスが速い

デメリット

  • デフォルトではローテーションなし——今日の主題そのもの
  • ホストに保存されるため、コンテナ削除でログも消える

向いているシーン:ローテーションを設定すれば、多くの環境で十分。

推奨設定

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

local ドライバー(推奨)

Docker 18.09 以降なら、こちらを強くおすすめします。

メリット

  • 自動ローテーション——手動設定なしでもサイズ制限
  • json-file より効率的なフォーマットで性能が良い
  • docker logs も利用可能

デメリット

  • Docker 18.09 以上が必要
  • バイナリ形式のため cat では読めない(通常は問題にならない)

向いているシーン:本番環境。手間が少なく性能も良い。

設定例

{
  "log-driver": "local",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  }
}

新規プロジェクトでは json-file より local を選ぶことが多いです。

journald ドライバー

systemd 系(Ubuntu 16.04+、CentOS 7+ など)向け。

メリット

  • OS ログと統合管理
  • 自動ローテーション
  • コンテナ ID などメタデータ付きの構造化ログ
  • docker logsjournalctl の両方が使える

デメリット

  • systemd 環境限定
  • journald に慣れていないと学習コストあり

向いているシーン:すでに systemd / journald ベースの運用体系がある場合。

設定例

{
  "log-driver": "journald"
}

journalctl で確認:

journalctl -u docker.service -f CONTAINER_NAME=my-app

syslog ドライバー

ログを syslog サーバーへ転送します。

メリット

  • リモート syslog で集中管理
  • TCP / UDP 対応(TCP の方が信頼性高い)
  • 既存 syslog 基盤と統合しやすい

デメリット

  • docker logs が使えない——現場調査が不便
  • ネットワーク遅延の可能性
  • syslog サーバーの運用が必要

向いているシーン:大規模クラスタで syslog 集中ログ基盤がすでにある場合。

設定例

{
  "log-driver": "syslog",
  "log-opts": {
    "syslog-address": "tcp://192.168.1.100:514",
    "syslog-facility": "daemon",
    "tag": "{{.Name}}/{{.ID}}"
  }
}

特別な理由がなければ、syslog はあまり推奨しません。docker logs が使えないのは地味に痛いです。

選び方の目安

シーン推奨ドライバー理由
単機・小規模クラスタlocal または json-file + ローテーションシンプルで docker logs も使える
systemd 環境journaldOS ログと統合
大規模クラスタfluentd / loki + ローカルドライバー集中ログ + ローカル応急用
既存 syslog ありsyslog + ローカルリモートとローカルの二重化

私の運用:小規模は local、大規模は json-file + Loki で集中管理し、ローカルには直近数百 MB を残して応急調査用にしています。

どのドライバーでも、ローカルログのサイズ上限は必須です。無制限はいずれディスクを破綻させます。

ベストプラクティスと運用のコツ

目の前の問題を片付けたら、長期運用の話をしましょう。

本番環境チェックリスト

本番を担当するなら、次を順に確認してください。

1. グローバルログ設定

{
  "log-driver": "local",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  }
}

または json-file:

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

2. 全コンテナの設定確認

全コンテナにローテーションが効いているか確認するスクリプト:

#!/bin/bash
for container in $(docker ps -q); do
  name=$(docker inspect --format='{{.Name}}' $container | sed 's/\///')
  logconfig=$(docker inspect --format='{{json .HostConfig.LogConfig}}' $container)
  echo "コンテナ: $name"
  echo "ログ設定: $logconfig"
  echo "---"
done

漏れがないか必ず実行。

3. 監視アラート

ディスク満杯になってからでは遅い。先にアラートを:

  • ディスク使用率 > 80%:警告
  • ディスク使用率 > 90%:重大
  • /var/lib/docker/containers/ のサイズが閾値超:警告

Prometheus + Grafana + Alertmanager の例:

- alert: HighDiskUsage
  expr: (node_filesystem_size_bytes - node_filesystem_free_bytes) / node_filesystem_size_bytes > 0.8
  for: 5m
  annotations:
    summary: "ディスク使用率が 80% を超えました"

4. 定期巡検

週次または月次でログチェック:

# Docker ディレクトリ全体
du -sh /var/lib/docker/

# コンテナログディレクトリ
du -sh /var/lib/docker/containers/

# 最大の json.log 上位 10 件
find /var/lib/docker/containers/ -name "*-json.log" -exec du -h {} \; | sort -h -r | head -10

異常があればすぐ対処。

アプリ層の最適化

インフラだけでなく、アプリ側も協力が必要です。

1. ログレベルの調整

本番で DEBUG / INFO は多すぎます。目安:

  • 本番:WARN または ERROR
  • テスト:INFO
  • 開発:DEBUG

これだけでログ量は 80% 以上減ることもあります。

2. 専用ログ基盤の利用

ログ量が非常に多いアプリは Docker ログだけに頼らない:

  • ELK(Elasticsearch + Logstash + Kibana)
  • Loki + Grafana(軽量)
  • マネージドのクラウドログ(AWS CloudWatch Logs、Google Cloud Logging など)

Docker ログは直近の少量だけ残し、応急調査用に。

3. 構造化ログ

JSON 形式で出力すると分析しやすい:

// 悪い例
console.log("ユーザーのログインに成功しました。ユーザー ID: " + userId);

// 良い例
console.log(JSON.stringify({
  level: "info",
  event: "user_login",
  userId: userId,
  timestamp: new Date().toISOString()
}));

4. ログサンプリング

リクエストログが多すぎる場合:

// 10% のリクエストだけ記録
if (Math.random() < 0.1) {
  console.log("HTTPリクエスト詳細...");
}

エラー時だけ詳細を出す方法も有効:

if (error) {
  console.log("詳細リクエスト情報: ", requestDetails);
}

よくある質問(FAQ)

Q1: daemon.json 変更後の Docker 再起動は稼働中コンテナに影響する?

A: コンテナは停止しません。ただし設定は新規コンテナのみ有効で、既存は再作成が必要です。

Q2: ログを空にするとアプリに影響する?

A: ありません。Docker がハンドルを保持したまま書き込みを続けるため、アプリは気づきません。

Q3: log-driver=journald なら max-size も必要?

A: 不要です。journald が独自にローテーションします。

Q4: ローテーション設定したのにログが大きい

A: 次を確認:

  1. コンテナを再作成したか(daemon.json は新規のみ)
  2. 1 行が異常に巨大なログを出していないか(ローテーションはファイルサイズ基準)

Q5: /var/lib/docker/containers/ の古いログは削除できる?

A: ローテーション済みの旧ファイル(例:xxx-json.log.1.gz)は削除可。現在の xxx-json.log は truncate で空にし、rm は避けてください。

注意点まとめ

  1. daemon.json は新規コンテナのみ——既存は再作成
  2. 値は引用符必須——"max-size": "10m"
  3. truncate は安全、rm は危険
  4. ドライバーによって docker logs の可否が異なる——syslog は非対応
  5. daemon.json 変更後は Docker 再起動
  6. ログ設定は定期確認——新規デプロイの漏れ防止

一言で言えば:先に設定し、定期点検。ディスクがあふれてから慌てない。

結論

記事冒頭の午前 3 時のアラートに戻ります。

その夜は 30 分でログ削除、2 時間でローテーションと監視設定、全コンテナの再作成——朝 6 時までかかりました。

教訓は一つ。Docker ログ管理は軽視できません。普段は見えなくても、爆発すると大事故になります。

要点の整理:

応急時truncate で巨大ログを空にし、容量を確保してサービス復旧。

予防時:daemon.json でローテーション(max-size + max-file)、local または json-file を選択し、全コンテナを再作成して反映。

長期運用:ディスク監視アラート、ログ設定の定期確認、アプリ側のログ出力最適化。

Docker を使っているなら、今すぐ確認を:

  1. find /var/lib/docker/ -name "*.log" -exec ls -sh {} \; | sort -h -r | head -10 で巨大ログの有無
  2. /etc/docker/daemon.json にローテーション設定があるか
  3. docker inspect で全コンテナにログ制限が効いているか

深夜のアラートで目が覚める前に、済ませておきましょう。

役に立ったら、同じ落とし穴に落ちそうな仲間にも共有してください。少しでも多く眠れる時間を。

次に読む

Docker ログ削除の完全フロー

json.log でディスクがあふれない 5 つの方法:json.log の削除、ログローテーションの設定、ログドライバーの選択

⏱️ 目安時間: 30 分

  1. 1

    ステップ1: 問題の深刻さと応急削除を理解する

    問題の深刻さ:
    • 本番サーバーのディスク使用率が 100% になり、すべてのサービスが応答停止
    • 1 つのコンテナの xxx-json.log がなんと 82GB
    • Docker はデフォルトでログファイルサイズを制限しない
    • stdout と stderr の出力はすべて json.log に書き込まれ、ディスクが満杯になるまで増え続ける

    応急で巨大ログを削除:
    • truncate でログを空にする:
    truncate -s 0 /var/lib/docker/containers/<container-id>/<container-id>-json.log
    • またはログファイルを削除してコンテナを再起動し、すぐにディスク容量を確保
  2. 2

    ステップ2: ログローテーションを設定しサイズを制限する

    ログローテーションの設定:
    • daemon.json で log-opts を設定(max-size: 10m、max-file: 3)
    • 1 ファイルあたりの最大サイズと保持ファイル数を制限
    • ログを自動ローテーションし、無限増殖を防ぐ

    設定例:
    • /etc/docker/daemon.json に追加:
    {
    "log-driver": "json-file",
    "log-opts": {
    "max-size": "10m",
    "max-file": "3"
    }
    }
    • Docker を再起動:systemctl restart docker

    サイズ制限:
    • max-size で 1 ファイルの上限(10m、50m など)
    • max-file で保持世代数(3、5 など)
    • 上限超過時は古いログを自動削除
  3. 3

    ステップ3: ログドライバーを選びベストプラクティスを適用する

    ログドライバーの選択:
    • json-file(デフォルト、開発向け)
    • syslog(本番向け、集中管理)
    • journald(systemd 環境向け)
    • none(ログ無効)
    • シーンに応じて適切なドライバーを選ぶ

    ベストプラクティス:
    • ログローテーションを設定しサイズを制限
    • 適切なログドライバーを使う
    • 古いログを定期削除:docker system prune
    • ディスク使用率を監視しアラートを設定
    • ログ設定を定期確認し、新規デプロイのコンテナ漏れを防ぐ

    一言で言えば:先に設定し、定期点検。ディスクがあふれてから慌てない。

FAQ

なぜ Docker のログファイルはディスクを食いつぶすのか?
問題の深刻さ:
• 本番サーバーのディスク使用率が 100% になり、すべてのサービスが応答停止
• 1 つのコンテナの xxx-json.log がなんと 82GB
• Docker はデフォルトでログファイルサイズを制限しない
• stdout と stderr の出力はすべて json.log に書き込まれる
• ディスクが満杯になるまで増え続ける

ログの場所:/var/lib/docker/containers/<container-id>/<container-id>-json.log。各コンテナのログはここに保存され、ローテーション未設定だと無限に肥大化します。
Docker ログを応急削除するには?
応急で巨大ログを削除:
• truncate でログを空にする:
truncate -s 0 /var/lib/docker/containers/<container-id>/<container-id>-json.log
• またはログを削除してコンテナを再起動し、すぐに容量を確保

巨大ログを探す:
• find で大きいファイルを検索:
find /var/lib/docker/containers -name '*-json.log' -size +1G
• du でディレクトリサイズを確認:
du -sh /var/lib/docker/containers/*
• 容量を食っているログを特定
Docker のログローテーションはどう設定する?
ログローテーション:
• daemon.json の log-opts(max-size: 10m、max-file: 3)
• 1 ファイルの上限と保持数を制限
• 自動ローテーションで無限増殖を防ぐ

設定例:
• /etc/docker/daemon.json に追加:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
• Docker 再起動:systemctl restart docker

サイズ制限:
• max-size で 1 ファイル上限(10m、50m など)
• max-file で保持世代(3、5 など)
• 超過分は古いログを自動削除
Docker ログ削除のベストプラクティスは?
ベストプラクティス:
• ログローテーションでサイズを制限
• 適切なログドライバーを使う
• 古いログを定期削除:docker system prune
• ディスク使用率を監視しアラート設定
• ログ設定を定期確認し、新規デプロイ漏れを防ぐ

一言で言えば:先に設定し、定期点検。ディスクがあふれてから慌てない。docker inspect で全コンテナにログ制限が効いているか確認し、深夜のアラートで気づく前に対策を。

6分で読めます · 公開日: 2025年12月18日 · 更新日: 2026年6月8日

関連記事

コメント

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