はじめに:なぜDocker×Xdebugの連携は「沼」と化すのか?
テックリードの私たちが、新規プロジェクトの立ち上げや既存システムのコンテナ化を進める際、必ずと言っていいほど直面するのが「Dockerコンテナ内のPHPと、ホストマシンのIDE(PhpStormやVS Code)間におけるリモートデバッグの確立」という壁です。
「`var_dump()`や`Log::info()`を仕込ってはコンテナを再ビルドし、ログの海から目的の配列を探し出す」——そんな前時代的なデバッグ手法に、チームの大切な開発リソースをドブに捨てるのはもう終わりにしましょう。
Xdebugは単なるブレークポイント停止ツールではありません。変数スコープのリアルタイム改変、例外発生時のスタックトレース解析、そして非同期リクエストやキューワーカーの内部挙動を丸裸にする、現代のPHP開発において唯一無二の「不可視領域の可視化装置」です。
本記事では、Docker(Laravel Sail / 自製環境を問わず)でXdebug 3を完全稼働させ、あなたのIDEとシームレスに接続するための「実務の現場でそのまま使える完全設定テンプレート」と、チームの生産性を劇的に跳ね上げるプロのノウハウを余すところなく伝授します。
—
1. 内部アーキテクチャの理解:なぜ接続は失敗するのか?
まず、データがどのように流れるのかというトポロジー(ネットワーク構造)を把握してください。
[ ホストマシン (IDE) ] <--- (DBGpプロトコル: デフォルトPort 9003) --- [ Dockerコンテナ (PHP-FPM) ] ここで最大の障壁となるのが、Dockerコンテナはホストマシンから見て独立したネットワーク空間(仮想ルーターの内側)にいるという点です。コンテナからホスト側に向かって「私にデバッグ接続してくれ」と通信(リバース接続)を送る際、ホストのIPアドレスを動的に解決する必要があります。
- Linux環境: `host.docker.internal` がデフォルトでは解決しないため、Dockerネットワークのルーティング設定(`extra_hosts` や `host-gateway`)が必須。
- Mac / Windows環境: Docker Desktopが提供するマジックホスト名 `host.docker.internal` を利用してホストへ到達。
この「双方向の通信経路」と「マッピング(パスの整合性)」さえクリアすれば、Xdebugの挙動は極めて安定します。
—
2. 実用的な設定ファイル(YAML / INI / JSON)のベストプラクティス構成例
チーム全員が「ワンコマンド」でデバッグ環境を立ち上げられるよう、実務で採用すべき洗練された設定ファイルの構成を公開します。
① `docker-compose.yml` (コンテナのネットワークとXdebug用環境変数の定義)
Laravelの公式開発環境であるLaravel Sailや、一般的なLEMP環境を想定したDocker Composeの抜粋です。
version: ‘3.8’
services:
laravel.test:
build:
context: ./docker/8.2 # PHP 8.2前提のDockerfileパス
dockerfile: Dockerfile
ports:
- “${APP_PORT:-80}:80”
environment:
# Xdebug 3のモード設定(debugを有効化し、スクリプト開始時に即座に接続を試みる)
XDEBUG_MODE: “${XDEBUG_MODE:-debug}”
# 接続トリガー(request: リクエスト毎に発火, trigger: クッキーやパラメーターがある場合のみ)
XDEBUG_TRIGGER: “${XDEBUG_TRIGGER:-trigger}”
# IDE側へ通知する際のホスト側のIP(Dockerホストへのルーティングを動的指定)
XDEBUG_CONFIG: “client_host=host.docker.internal client_port=9003”
extra_hosts:
# Linux環境でも host.docker.internal がホストマシンを指すように強制マッピング
- “host.docker.internal:host-gateway”
volumes:
- .:/var/www/html
networks:
- sail
networks:
sail:
driver: bridge
② `xdebug.ini` (PHPコンテナ内のXdebug拡張モジュール設定)
Dockerfile内でコンテナにビルドイン、あるいはマウントする `xdebug.ini` の極限までチューニングされた設定です。
; Xdebug拡張モジュールのロード(環境によりパスが異なる場合は拡張子のみ指定)
zend_extension=xdebug.so
[xdebug]
; デバッグ機能と、プロファイル機能(必要に応じてプロファイリングも同時稼働可能)
xdebug.mode = debug,develop
; IDEとの通信ポート(Xdebug 3の標準は9003。Xdebug 2の9000から変更されている点に注意)
xdebug.client_port = 9003
; ホストマシンの指定(Docker環境では host.docker.internal を指定)
xdebug.client_host = host.docker.internal
; スクリプトの実行開始と同時に自動でデバッグ接続を開始する(開発効率化のため ‘yes’ 推奨)
xdebug.start_with_request = yes
; IDEキー(PhpStorm等のIDE側で待ち受ける際の識別子。任意だが ‘PHPSTORM’ や ‘VSCODE’ が一般的)
xdebug.idekey = “PHPSTORM”
; 例外発生時やエラー時に自動でスタックトレースを詳細に出力
xdebug.discover_client_host = true
③ VS Code用設定:`.vscode/launch.json`
VS Codeでデバッグを完全に機能させるための設定です。Dockerコンテナ内の絶対パスと、ホストマシンのプロジェクトルートパスを正確にマッピング(`pathMappings`)することが極意です。
{
“version”: “0.2.0”,
“configurations”: [
{
“name”: “Listen for Xdebug (Docker Laravel)”,
“type”: “php”,
“request”: “launch”,
“port”: 9003,
“pathMappings”: {
// コンテナ内のドキュメントルート : ホストマシンのワークスペースパス
“/var/www/html”: “${workspaceFolder}”
},
// ログを出力してデバッグ接続のトラブルシューティングを容易にする(本番運用時はfalse推奨)
“log”: true
}
]
}
—
3. 開発スピードを劇的に高める隠れたキーボードショートカット&神プラグイン
IDEのポテンシャルを極限まで引き出し、デバッグ作業を「苦行」から「快感」に変える実戦テクニックです。
PhpStormで絶対入れるべき設定・ショートカット
- 「Start Listening for PHP Debug Connections」ボタン(電話のアイコン)を常にONに
- Shortcut: `Ctrl + Alt + F5` (Windows/Linux) / `Cmd + Shift + F8` 周辺にカスタム割当
- Evaluate Expression (`Alt + F8` / `Option + F8`):
- ブレークポイント停止中に、その場で任意のEloquentクエリ(例: `User::with(‘posts’)->find(1)`)を実行し、結果のコレクションを即座に評価できます。
- Force Run to Cursor (`Alt + F9` / `Option + F9`):
- 無駄に何度もステップオーバー(F10)を繰り返さず、カーソル行まで一気に処理をジャンプさせます。
VS Codeで入れるべき「神プラグイン」
- PHP Debug (`felixfbecker.php-debug`):
- これなしでは始まらない、VS CodeにおけるXdebug連携のデファクトスタンダード。
- PHP Intelephense (`bmewburn.vscode-intelephense-client`):
- 高速な補完だけでなく、定義ジャンプやリファクタリングの精度が跳ね上がります。Docker環境下でも適切にパス設定を行うことで、コンテナ内のベンダーライブラリまで完璧にインデックス化されます。
—
4. チーム開発で役立つ設定の共有化ルール
「私の環境では動くが、隣のメンバーの環境ではデバッグがヒットしない」——この属人化を排除するため、以下のガバナンスルールをチームに強制・共有してください。
1. 環境変数の `.env.example` への完全な組み込み
- `XDEBUG_MODE=debug` や `XDEBUG_TRIGGER=trigger` などの変数を `.env` に標準搭載させ、チーム全体でXdebugの挙動を統一します。
2. IDE設定ファイル(`.vscode/` や `.idea/`)のチーム標準化
- VS Codeであれば `.vscode/launch.json` をGit管理下に置き、新規参画者がリポジトリをクローンしてF5を押すだけで即座にデバッグが開始できる状態を作ります。
3. CLIやArtisanコマンド、PHPUnit実行時のXdebug制御
- テスト実行時やキューワーカー起動時に常にXdebugが有効だと、パフォーマンスが著しく低下します。コマンド実行時は環境変数を上書きするエイリアスをチームで共有しましょう。
【プロの技】テスト時は一時的にXdebugを無効化して爆速でPHPUnitを実行するシェルエイリアス
alias ptest=”XDEBUG_MODE=off php artisan test”
—
5. トラブルシューティング:接続できないときのチェックリスト
もしブレークポイントで止まらない場合は、以下の順番でパケットと設定を流れるように確認してください。
1. IDEのリスナー(受話器アイコン)がアクティブか?
- 意外と多いのが、IDEがデバッグ信号の待ち受けモードになっていないケースです。
2. コンテナ内からホストへ疎通ができるか?
- コンテナ内に `docker exec -it
bash` で入り、`nc -zv host.docker.internal 9003` もしくは `curl` でホストに到達できるか確認します。
3. パスのマッピング(Path Mappings)が完全一致しているか?
- IDE側のログ(`pathMappings` の不一致警告)に注目してください。ホスト側の `/Users/hoge/project` とコンテナ側の `/var/www/html` が1文字たりともズレていない必要があります。
—
おわりに:デバッグ能力は、エンジニアの「解像度」に直結する
XdebugをDocker環境に正しく導入し、手なずけることは、単にバグを早く見つけるためのテクニックにとどまりません。フレームワークの内部構造(Laravelであればサービスコンテナの解決フローやミドルウェアのスタック)の「内部で何が起きているのか」を1行単位で解剖する力をあなたにもたらします。
「動くコードを書くエンジニア」から「システム全体の挙動を完全に支配するエンジニア」へ。
今日からあなたの開発環境をアップデートし、圧倒的なスピードと品質を手に入れてください。