🖥️

【3-6】Docker Compose実践編:コンテナ運用の必須スキル!監視・デバッグ・トラブルシューティング

に公開

Docker Compose実践編:コンテナ運用の必須スキル!監視・デバッグ・トラブルシューティング

はじめに

前回の記事では、docker-compose.ymlを使い、WordPressやNode.jsといった複雑なアプリケーション環境をコマンド一発で構築しました。しかし、docker compose up -d を実行するのは、いわば船を出港させる合図にすぎません。本当の航海(=本番運用)では、船が正常に動いているかを常に監視し、嵐(=予期せぬエラー)に見舞われたときには冷静に対処するスキルが不可欠です。
https://zenn.dev/koikoi_infra/articles/64a379dfe36d70

この記事では、前回構築したWordPress環境を題材に、本番運用で必須となるコンテナの監視手法と、誰もが一度は経験するトラブルシューティングの実践的な手順を深く掘り下げていきます。

実践:本番運用を見据えたコンテナ管理術

前回構築したWordPress環境 (~/wordpress-compose) を使って、運用の実践スキルを身につけていきましょう。

Step 1: コンテナの「声」を聞く 〜ログ監視と管理〜

コンテナの中で何が起きているかを知る最も基本的な方法が、ログの確認です。

まずは、リアルタイムでログを追跡してみましょう。-f (follow) オプションが便利です。

# 作業ディレクトリに移動
cd ~/wordpress-compose

# 全てのコンテナのログをリアルタイムで表示
docker compose logs -f

# WordPressだけのログを見たい場合
docker compose logs -f wordpress

監視を終了するには Ctrl + C を押します。

しかし、このままではログは無限に増え続け、いつかディスクを圧迫してしまいます。そこで、ログファイルのサイズや数に上限を設けるログローテーションを設定します。

設定を分離するため、docker-compose.override.yml というファイルに記述するのがスマートな方法です。

# docker-compose.override.yml を作成
cat > docker-compose.override.yml << 'EOF'
services:
  wordpress:
    logging:
      driver: "json-file"
      options:
        max-size: "10m" # 1ファイル10MBまで
        max-file: "3"   # 3ファイルまで保持

  db:
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
EOF

# 設定を適用してコンテナを再起動
docker compose up -d

これで、古いログは自動的に削除され、安心して運用を続けられます。

Step 2: コンテナの健康診断「ヘルスチェック」

「コンテナは起動しているのに、中のアプリケーションが応答しない…」これは非常によくある問題です。これを防ぐのがヘルスチェックです。コンテナが本当に正常に機能しているかを、Dockerが定期的にチェックしてくれます。

docker-compose.yml に設定を追記しましょう。(※前回のファイルに追記する形になります)

# nanoエディタでファイルを開く
nano docker-compose.yml

そして、wordpressdbの各サービスの定義の中に、healthcheckブロックを追加します。

# docker-compose.yml

services:
  wordpress:
    # ... imageやportsなどの既存設定 ...
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s

  db:
    # ... imageやenvironmentなどの既存設定 ...
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-proot_password"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s
# ... volumesやnetworksの定義 ...

ファイルを保存してコンテナを再起動し、しばらく待ってから状態を確認します。

docker compose up -d
docker compose ps

STATUS列に (healthy) と表示されれば、健康診断は成功です!

設定ファイルの上手な使い分け:「docker-compose.yml」vs「override.yml」

学習の途中で、「なぜログ設定は新しいoverride.ymlファイルを作ったのに、ヘルスチェックは既存のdocker-compose.ymlに追記したんだろう?」と疑問に思った方もいるかもしれません。私自身もその一人でした。

実は、これには設定をクリーンで管理しやすくするための、とても実践的な理由が隠されています。

🔹 docker-compose.yml = アプリケーションの「基本設計図」

このファイルは、アプリケーションの不変的な構造を定義する、いわば基本の設計図です。

  • どのサービス(wordpress, dbなど)が存在するのか?
  • どのサービスがどのサービスに依存しているのか(depends_on)?
  • どのネットワークに接続するのか?

このように、誰がどの環境で動かしても変わらないアプリケーションの核となる定義をここに記述します。

🔹 docker-compose.override.yml = 環境ごとの「カスタマイズ用の付箋」

一方、override.ymlは、その名の通り**基本設計図の設定を上書き(オーバーライド)**したり、追加の設定を加えたりするためのファイルです。これは、環境ごとの違いを吸収するための「付箋」のような役割を果たします。

では、なぜこのファイルが自動で読み込まれるのでしょうか?

特別な設定は一切不要です。docker composeコマンドは、実行時にdocker-compose.ymlを読み込んだ後、同じディレクトリにdocker-compose.override.ymlという名前のファイルがあれば、それを自動的に探し出して読み込むように設計されています。

そして、両方のファイルに同じ設定があれば、override.ymlの内容が優先されます。この「規約(決まったファイル名)に従うだけで自動的に機能が有効になる」仕組みのおかげで、私たちは複雑なコマンドを打つことなく、設定を柔軟にカスタマイズできるのです。

  • 「私の開発PCでは、8080番ポートは別のプログラムが使っているから8888番ポートに変えたい」
  • 「開発中はもっと詳細なログが見たいから、ログの設定だけ変更したい」
  • 「ローカルでのデバッグ用に、テストツール用のコンテナを追加したい」

このような、チームメンバーや実行環境(開発、本番など)によって変わりうる設定をoverride.ymlに分離することで、基本設計図 (docker-compose.yml) を汚さずに済みます。

🤔 今回のケースに当てはめてみると…

ログ設定 (override.ymlに記述)

ログの出力形式やローテーションは、まさに**「運用上の関心事」**です。開発環境と本番環境で設定を変えたい典型例なので、override.ymlに分離するのは非常に理にかなっています。

ヘルスチェック (docker-compose.ymlに追記)

ヘルスチェックは、「そのサービスが**『正常である』とはどういう状態か**」を定義する、サービス自身の基本的な仕様の一部と捉えることができます。これは環境によって変わるものではないため、基本設計図であるdocker-compose.ymlに含めておくのが自然、という判断です。

もちろん明確なルールがあるわけではありませんが、この「不変の定義か、環境依存のカスタマイズか」という軸でファイルを使い分けることで、プロジェクトが大きくなっても非常に見通しの良い構成を保つことができます。

ちなみに、docker-compose.override.yml.gitignoreファイルに追加して、チームメンバー各自が自分用の設定を書き込めるようにすることもよくあります。このテクニック、ぜひ覚えておいてください!

Step 3: 【本編】エラー発生!実践トラブルシューティング

ここからがこの記事の核心です。学習中に私が実際に遭遇したエラーを例に、解決までの道のりを追体験してみましょう。

現象の確認:DBが再起動を繰り返し、WordPressが不健康に!

healthcheckを設定して docker compose up -d を実行した後、docker compose ps で状態を確認すると、以下のような絶望的な表示が…。

NAME                         IMAGE        STATUS                    PORTS
wordpress-compose-db-1       mysql:8.0    Restarting (1) 5 sec ago
wordpress-compose-wordpress-1  wordpress    Up 1 minute (unhealthy)   0.0.0.0:8080->80/tcp

DBコンテナが Restarting を繰り返し、WordPressは unhealthy になっています。この状況から、根本原因はDBコンテナにあり、それに依存するWordPressが巻き添えを食らっていると推測できます。

原因の特定:ログに刻まれたエラーメッセージ

原因を突き止めるため、問題のdbコンテナのログを深く調査します。

docker compose logs db | grep -i "error"

大量のログが出力されますが、焦らず [ERROR] というキーワードを探します。すると、以下のような致命的なエラーが見つかりました。

db-1 | [ERROR] [MY-010020] [Server] Data Dictionary initialization failed.
db-1 | [ERROR] [MY-010119] [Server] Aborting

Data Dictionary initialization failed。これは、MySQLが自身の設計図や目次とも言えるデータ辞書の初期化に失敗し、起動を諦めている(Aborting)ことを示しています。これは、度重なる起動・停止によって、データを保存しているボリューム内に中途半端なファイルが作られてしまったことが原因です。

解決策:Docker Composeの「黄金リセット手順」

原因が「壊れたデータボリューム」だと分かれば、解決策はシンプルです。コンテナと問題のボリュームを一度完全に削除し、まっさらな状態から再構築します。

以下の3ステップは、Docker Composeで原因不明のトラブルに陥った際の黄金パターンです。

Step 1: すべてのコンテナを停止・削除する

docker compose down

Step 2: 問題のデータボリュームを削除する

これが最も重要です。壊れたデータを完全に消去します。

docker volume rm wordpress-compose_mysql-data

Step 3: クリーンな状態でコンテナを再作成・起動する

まっさらなディスク(ボリューム)上に、コンテナが正常なデータを作成します。

docker compose up -d

1分ほど待ってから、再度 docker compose ps で状態を確認すると…

NAME                         IMAGE        STATUS                   PORTS
wordpress-compose-db-1       mysql:8.0    Up 1 minute (healthy)    3306/tcp, 33060/tcp
wordpress-compose-wordpress-1  wordpress    Up 1 minute (healthy)    0.0.0.0:8080->80/tcp

見事、両方のコンテナが (healthy) 状態に! これでトラブルは解決です。

まとめ

Docker Composeで環境を「作る」スキルに、今回学んだ「守り、治す」スキルが加わることで、あなたの開発・運用能力は大きく向上します。エラーは決して怖いものではなく、解決する過程でこそ、本当の実力が身につくのです。

Discussion