トラブルシューティング:一般的なDockerコンテナエラーを迅速に診断する
Dockerコンテナは堅牢であるように設計されていますが、起動失敗は開発ライフサイクルにおいて避けられない要素です。コンテナが予期せず終了した場合、デプロイ速度を維持するためには、根本原因を迅速に理解することが不可欠です。これらの失敗は、ゼロ以外の終了コードによって示されるだけで、分かりにくいことがよくあります。
本ガイドでは、必須のDockerコマンドツールキットを使用した専門的なトラブルシューティング手法を紹介します。ここでは、docker ps、docker logs、docker inspectを活用して、最も頻繁に発生するコンテナ起動の問題を迅速に特定し解決するための体系的な診断プロセスを順を追って説明します。これにより、推測から脱却し、実用的な修正を適用できるようになります。
フェーズ1:初期トリアージと状態評価
コンテナの障害を診断する最初のステップは、現在および直近の状態を確認することです。デフォルトのdocker psコマンドは実行中のコンテナのみを表示するため、起動直後にコンテナが終了した場合、これは役に立ちません。
失敗の特定にdocker ps -aを使用する
初期トリアージに不可欠なコマンドはdocker ps -a(すべてのコンテナ、実行中または停止中をリスト表示)です。これにより、停止したコンテナのステータス、終了コード、経過時間を確認できます。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2d3f4b5c6e7a my-app:latest "/usr/bin/start.sh" 5 minutes ago Exited (127) 3 minutes ago web-service
d8c9a0b1c2d3 nginx:latest "nginx -g 'daemon..." 10 minutes ago Up 8 minutes 80/tcp active-proxy
主要なステータスインジケータ:
- Exited (0): コンテナが正常かつ意図的にシャットダウンしました(バッチジョブ完了後など)。診断は通常最小限で済みます。
- Exited (ゼロ以外): 障害が発生しました。一般的なゼロ以外のコード(1、126、127)は、プロセスのクラッシュ、ファイルが見つからない、権限エラーなど、重大な問題を示します。
- Created: コンテナは作成されましたが、起動しなかったか、ステータスが更新される前に起動に失敗しました。
フェーズ2:コンテナログによる深掘り
コンテナIDまたは名前が分かったら、診断にとって最も価値のある単一のツールはロギングメカニズムです。Dockerは、コンテナの主要プロセスからの標準出力(stdout)と標準エラー(stderr)ストリームをキャプチャします。
履歴ログの取得
失敗したコンテナからキャプチャされたすべての出力を取得するには、docker logsコマンドを使用します。この出力には、コンテナの停止を引き起こした正確なエラーメッセージ(スタックトレース、設定エラー、ファイル欠落の警告など)が含まれていることがよくあります。
# 失敗したコンテナのログを取得
$ docker logs web-service
# --- ログ出力例 ---
Standardizing environment...
Error: Configuration file not found at /etc/app/config.json
Application initialization failed. Exiting.
高度なログフィルタリングのヒント:
| コマンドオプション | 目的 | 例 |
|---|---|---|
-f, --follow |
ログをリアルタイムでストリーミング(コンテナが素早く起動してクラッシュする場合に便利)。 | docker logs -f web-service |
--tail N |
ログの最後のN行のみを表示。 | docker logs --tail 50 web-service |
-t, --timestamps |
各ログエントリにタイムスタンプを表示(イベントの関連付けに役立つ)。 | docker logs -t web-service |
--since |
特定の時刻または期間(例:1h、15m)以降に生成されたログを表示。 |
docker logs --since 15m web-service |
ベストプラクティス: 障害発生後、必ずすぐにログを確認してください。ログが空の場合、障害はメインアプリケーションプロセスが起動する前に発生したことを意味し、多くの場合、Dockerの
ENTRYPOINTまたはCMD設定自体に問題があることを示唆しています。
フェーズ3:docker inspectによる状態と設定の分析
ログが不十分な場合(たとえば、一般的なエラーが表示されるか、何も表示されない場合)、コンテナの内部設定と実行環境を分析する必要があります。
完全な状態オブジェクトの確認
docker inspectは、ネットワーク設定からリソース制限に至るまで、コンテナに関するすべてを詳述する包括的なJSONオブジェクトを提供し、決定的に最終的な状態とエラーメッセージも提供します。
$ docker inspect web-service
出力内の以下の主要なJSONパスに焦点を当ててください。
1. 状態情報
このセクションには、障害発生時刻やシステムレベルのエラーメッセージ(該当する場合)を含む詳細な終了情報が格納されています。
...
"State": {
"Status": "exited",
"Running": false,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 0,
"ExitCode": 127,
"Error": "", // 多くの場合空ですが、カーネルレベルのメッセージを含むことがあります
"StartedAt": "2023-10-26T14:30:00.123456789Z",
"FinishedAt": "2023-10-26T14:30:00.223456789Z"
},
...
2. エントリポイントとコマンド
コンテナがコード127(コマンドが見つからない)または126(コマンドが実行可能でない)で終了した場合、メインプロセスが正しく指定されており、イメージ内にパスが存在することを確認するために、ConfigまたはStateセクションの下のPathとArgsを確認します。
...
"Config": {
"Entrypoint": [
"/usr/bin/start.sh"
],
"Cmd": [
"--mode=production"
],
...
3. マウントとボリューム
アプリケーションがファイル不足や権限エラーで失敗した場合、Mountsセクションを確認して、ホストボリュームが正しくマッピングされ、アクセス可能であり、必要な権限を持っていることを確認します。
フェーズ4:一般的な起動失敗シナリオと解決策
ログと検査データを組み合わせることで、障害を分類し、的を絞った修正を適用できます。
シナリオ1:ポートが既に使用中(バインドエラー)
これは、マッピングしようとしているホストポート(-p 8080:80)が、別のコンテナまたはホストマシン上で実行されている別のプロセスによって既に使用されている場合に発生します。
診断: コンテナはすぐに起動に失敗するか、ログにbind: address already in useのようなエラーが表示されます。
解決策:
1. 競合しているプロセスまたはコンテナを停止します。
2. ホストポートマッピングを変更します(例:-p 8081:80)。
シナリオ2:コマンドが見つからない(終了コード127)
これは、DockerランタイムがENTRYPOINTまたはCMDディレクティブで指定されたコマンドを実行できなかったことを意味します。
診断: docker logs(空の場合がある)を確認し、docker inspectを使用してConfigセクションを検証します。
解決策:
1. 実行可能ファイルのパスが正しいこと(例:appではなく/usr/local/bin/app)を確認します。
2. 実行可能ファイルがイメージ内に存在することを確認します。イメージのファイルシステムを調べるために、一時的なデバッグコンテナを実行する必要がある場合があります。
# 失敗したコマンドをオーバーライドして、イメージを一時的に実行
$ docker run -it --entrypoint /bin/bash my-app:latest
# コンテナ内で、以下を確認: ls -l /usr/bin/start.sh
シナリオ3:アクセスが拒否されました(終了コード126またはボリュームエラー)
通常、コンテナユーザーが必要なファイル、ディレクトリ、またはボリュームマウントポイントにアクセスする権限がない場合に発生します。
診断: ログにPermission deniedやcannot open fileなどのエラーが表示されます。
解決策:
1. ボリュームの権限: ホストマウント(-v /host/data:/container/data)を使用している場合は、ホストフォルダーがコンテナが実行されるユーザー(多くの場合UID 1000またはroot)に対して読み書き権限を持っていることを確認します。
2. エントリポイントの権限: ENTRYPOINTで指定されたスクリプトが、Dockerfile内で実行可能フラグ(RUN chmod +x /path/to/script)が設定されていることを確認します。
シナリオ4:メモリ不足(OOMKilled)
これは、カーネルが過剰なメモリ消費のためにコンテナの主要プロセスを終了させるシステムレベルの障害です。
診断: docker ps -aでSTATUS Exited (137)を確認するか、docker inspect [id]を実行し、Stateオブジェクトで"OOMKilled": trueのフィールドを探します。
解決策:
1. -mフラグ(例:--memory 2g)を使用して、コンテナのメモリ制限を増やします。
2. メモリ使用量を削減するようにアプリケーションを最適化します。
まとめと次のステップ
効率的なDockerトラブルシューティングは、体系的なアプローチに依存します。docker ps -aから始めて障害を評価し、主要な調査ツールとしてdocker logsを使用し、より深い設定や環境の問題についてはdocker inspectを予約します。終了コードの意味と、コンテナの状態のどこを見るべきかを理解することで、一般的な起動障害の解決に費やす時間を大幅に短縮できます。
今後のアクション:
- 問題がイメージに関連している場合は、Dockerfileに一時的なデバッグ手順(例:環境変数の表示)を含めてイメージを再構築します。
- ログが不足している場合は、一時的にコンテナの初期化を
bashまたはshに切り替えて、ファイルシステムを手動でナビゲートし、環境内でコマンドをテストします。