Docker: ログ記録と監視

最終更新:2026-08-26

深夜 3 時にコンテナがクラッシュした——そんなとき、ログと監視が根本原因を素早く特定する唯一の手段です。

1. 学べること



2. 運用エンジニアの実話

(1) 悩み: 深夜 3 時の OOM アラートに手がかりなし

深夜 3 時、本番環境のコンテナが突然メモリ使用量を急増させ OOM エラーを起こしました。Charlie はアラートで叩き起こされますが、原因がわかりません。ログファイルは 2 GB、docker logs は流れるのが速すぎて肝心な情報を探せず、過去のリソース監視データもない——手探り状態でした。

(2) ログフィルタリングとリソース監視による解決

Charlie は docker logs --since と grep を組み合わせて、30 秒で異常リクエストを突き止めました。

BASH
# 直近 2 時間の OOM 関連ログを探す
docker logs --since 2h --tail 500 app 2>&1 | grep -i "oom\|memory\|error"

# リソース使用履歴を確認
docker stats --no-stream

(3) 効果: 30 秒で根本原因を特定

2 GB のログの中から、30 秒で OOM イベントと異常リクエストを特定しました。Charlie はその後ログローテーションと Prometheus アラートを設定し、次回以降の深夜アラートには自動的に根本原因が含まれるようにしました。



3. Docker のログドライバー

(1) 4 種類のログドライバー

100%
graph LR
    CTN["コンテナ<br/>stdout/stderr"] --> DRV["ログドライバー"]
    DRV --> JSON["json-file<br/>デフォルト、ローカルファイル"]
    DRV --> JRN["journald<br/>systemd ログ"]
    DRV --> SYS["syslog<br/>リモートログサーバー"]
    DRV --> GELF["gelf<br/>ELK/Loki"]
ドライバー 保存場所 ローテーション 集中管理 ユースケース
json-file(デフォルト) /var/lib/docker/containers/ 手動設定が必要 スタンドアロン開発
journald systemd ジャーナル ✅ 自動 systemd 環境
syslog リモート syslog サーバー ✅ サーバー側 従来のログ基盤
gelf ELK / Loki ✅ サーバー側 集中ログプラットフォーム
local ローカルファイル(最適化形式) ✅ 自動 軽量なローカルログ
なし ログを記録しない - - 高性能 / 機密データ

(2) ログドライバーの設定

BASH
# コンテナ個別: 起動時にログドライバーを指定
docker run -d \
  --log-driver json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  --name app myapp:1.0
JSON
// グローバル: /etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}


4. docker logs の高度な使い方

▶ サンプル: --since で時間フィルタ (難易度: ⭐⭐)

BASH
# 直近 2 時間のログを表示
docker logs --since 2h app

# 特定の時刻以降のログを表示
docker logs --since "2024-01-15T03:00:00" app

# 2 つのタイムスタンプ間のログを表示
docker logs --since "2024-01-15T03:00:00" --until "2024-01-15T04:00:00" app

▶ サンプル: --tail で行数を制限 (難易度 ⭐)

BASH
# 末尾 100 行を表示
docker logs --tail 100 app

# 末尾 100 行をリアルタイムで追跡
docker logs -f --tail 100 app

▶ サンプル: docker stats でリアルタイム監視 (難易度: ⭐⭐)

BASH
# 全コンテナのリソース統計をリアルタイム表示
docker stats

# ワンショットスナップショット(ストリームなし)
docker stats --no-stream

# 特定コンテナの統計
docker stats app db --no-stream

# カスタムフォーマット
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
💻 出力:

TEXT 📖 参照専用
NAME   CPU %   MEM USAGE / LIMIT
app    2.35%   150MiB / 512MiB
db     0.50%   85MiB / 256MiB

▶ サンプル: docker events でイベント追跡 (難易度: ⭐⭐)

BASH
# Docker デーモンのイベントをストリーム
docker events

# イベントタイプでフィルタ
docker events --filter type=container

# 特定のイベントでフィルタ
docker events --filter event=oom --filter event=die

# 時間帯でフィルタ
docker events --since "2024-01-15T03:00:00" --until "2024-01-15T04:00:00"
💻 出力:

TEXT 📖 参照専用
2024-01-15T03:24:15Z container oom 67890... (name=app, image=myapp)
2024-01-15T03:24:15Z container die 67890... (exitCode=137, name=app)
2024-01-15T03:24:25Z container start 67890... (name=app, image=myapp)


5. ログローテーション戦略

(1) json-file のログローテーション

パラメーター 機能 推奨値
max-size 単一ログファイルの最大サイズ 10m
max-file 保持するログファイルの最大数 3
labels ログに付与するラベル -
tag ログタグのテンプレート -

▶ サンプル: ログローテーションの設定 (難易度: ⭐⭐)

BASH
# コンテナ起動時にログローテーションを設定
docker run -d \
  --log-driver json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  --name app myapp:1.0
💡 ヒント: ログローテーションを設定していないコンテナは「時限爆弾」です——ログファイルは無限に増え続け、ディスクを埋め尽くします。本番環境では必ず max-sizemax-file を設定するか、ローテーションを内蔵した local ログドライバーを使ってください。

(2) Compose でのログ設定

YAML
services:
  api:
    image: myapp:1.0
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"


6. 集中ログ収集ソリューション

(1) 3 つの選択肢の比較

ソリューション 構成要素 複雑度 適用規模
docker logs 組み込み 単一マシン / 開発
ELK スタック Elasticsearch + Logstash + Kibana ⭐⭐⭐ エンタープライズ規模
Loki + Grafana Loki + Promtail + Grafana ⭐⭐ 中小規模 / クラウドネイティブ


7. 完全なサンプル: ログローテーションと監視の設定

BASH
# ============================================
# 完全なウォークスルー: ログローテーション + 監視
# 内容: ログローテーション、stats、events、OOM 診断
# ============================================

# 1. ログローテーション付きでアプリを起動
docker run -d \
  --name app \
  --log-driver json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  --memory=256m \
  --restart=on-failure:5 \
  -p 5000:5000 \
  myapp:1.0

# 2. リソース使用量を監視
docker stats app --no-stream

# 3. シミュレーション: メモリ超過で OOM を発生させる
docker exec app python -c "
import numpy as np
x = np.zeros((50000, 50000))  # 約 20GB の割り当てを試行
"

# 4. OOM イベントをキャプチャ
docker events --filter event=oom --since 1m

# 5. ログから OOM をタイムスタンプ付きで探す
docker logs --since 5m --tail 200 app 2>&1 | grep -i "oom\|memory\|killed"

# 6. 終了コードを確認
docker inspect app --format='ExitCode: {{.State.ExitCode}}, OOMKilled: {{.State.OOMKilled}}'

# 7. 直近 1000 行をエクスポートして解析
docker logs --tail 1000 app > app-debug.log 2>&1

# 8. ログローテーションが動作していることを確認
ls -la /var/lib/docker/containers/$(docker inspect app --format='{{.Id}}')/


❓ よくある質問

Q ログファイルが大きすぎるとディスクに影響しますか?
A はい、影響します。デフォルトの json-file ドライバーはログをローテーションしないため、ログファイルは無限に増大します。本番環境で 1 つのコンテナのログファイルが 50 GB に達した事例もあります。起動時に必ず --log-opt max-size=10m --log-opt max-file=3 を設定するか、デーモン.json でグローバルにデフォルトローテーションを設定してください。
Q ログローテーションを設定するには?
A 2 つの方法があります: ① コンテナ起動時に --log-opt max-size=10m --log-opt max-file=3 を指定する; ② /etc/docker/daemon.json のグローバル設定に "log-opts": {"max-size": "10m", "max-file": "3"} を記述する。本番環境では設定漏れを防ぐためグローバル設定を推奨します。
Q 複数コンテナのログを集中収集するには?
A gelf または syslog ログドライバーを使い、全コンテナのログを集中 ELK / Loki プラットフォームへ送信します。より推奨される方法: json-file ドライバーのまま、Filebeat / Promtail でログファイルを収集します——そうすれば docker logs も引き続き使えます。
Q コンテナ再起動後もログは残っていますか?
A はい、残っています。コンテナ再起動ではログファイルは削除されません。ただし docker rm でコンテナを削除するとログも消えます。ログを永続化するには: ① アプリケーションログをファイルに書いてボリュームにマウントする; ② 集中ログプラットフォームでリアルタイム収集する。
Q docker stats のメモリ表示はコンテナのものかプロセスか?
A コンテナ全体です。docker stats はコンテナ内全プロセスの cgroup メモリ使用量合計を表示します。LIMIT--memory で設定した上限です。--memory を設定していない場合、LIMIT はホストの全メモリが表示されます。

📖 まとめ


📝 練習問題

  1. 基本練習 (難易度 ⭐): コンテナを起動し --log-opt max-size=5m --log-opt max-file=2 を設定、その後 docker logs でログを確認し、ローテーションが効いているか検証してください。
  2. 応用問題 (難易度 ⭐⭐): 負荷テスト中に docker stats でコンテナを監視し、CPU とメモリのピーク使用量を記録してください。
  3. 挑戦 (難易度: ⭐⭐⭐): docker events でコンテナの OOM イベントをキャプチャし、docker logs --since を組み合わせて OOM を引き起こしたリクエストまたは処理を特定してください。
Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%