xdebug.ini / launch.json / pathMappings の最小構成を組み合わせ、localhost:8080 への HTTP アクセスで VS Code のブレークポイントに停止する環境を作ります。
対象は WSL2 + Docker + Remote - WSL で PHP を開発中の方です。既存プロジェクトは不要で、記事内で新規デモ環境を作成します。「CLI では見えているのに止まらない」の原因と対処も含みます。
前提環境
- Windows 11
- WSL2(Ubuntu)
- VS Code(Remote - WSL)
- Docker Desktop(WSL連携有効)
以降のコマンドは、特記がない限り WSL 側ターミナルで実行します。
code --list-extensions も WSL 側で実行してください。
1. ゴールと非対象
この記事で到達する状態:
localhost:8080への HTTP アクセスで、VS Code のブレークポイントに停止できるxdebug.ini/launch.json/ 最小サンプルの組み合わせを再現できるstart_with_request=yesからtriggerへ段階的に切り替えられる
前提条件:
- VS Code 拡張
xdebug.php-debugは導入済みとする(未導入の場合は 2 章で導入可能)
この記事で扱わない内容:
- 本番環境での Xdebug 運用
- 高度な条件付きブレークポイントや PHPUnit 連携
- PhpStorm など他 IDE との比較
主線は start_with_request=yes です。
trigger は 6 章で任意の運用改善として扱います。
2. 新規デモ環境を作成する(Remote - WSL / Docker)
まず、WSL 側にデモディレクトリを作成します。
mkdir -p ~/projects/vscode-xdebug-step-debug-demo
cd ~/projects/vscode-xdebug-step-debug-demo
mkdir -p docker/php/conf.d .vscode public
code .
docker/php/Dockerfile を作成します。
FROM php:8.5-cli
RUN pecl install xdebug \
&& docker-php-ext-enable xdebug
WORKDIR /var/www/html
compose.yml を作成します(この章では最小起動構成のみ)。
services:
app:
build:
context: .
dockerfile: docker/php/Dockerfile
working_dir: /var/www/html
volumes:
- ./:/var/www/html
command: ["php", "-S", "0.0.0.0:8080", "-t", "/var/www/html/public"]
ports:
- "8080:8080"
起動して前提を確認します。
docker compose up --build -d
docker compose ps
docker compose exec app php -v
docker compose exec app php -m | grep -i xdebug
code --list-extensions | grep -Fx "xdebug.php-debug"
xdebug.php-debug が見つからない場合は、WSL 側で導入してから続行してください。
code --install-extension xdebug.php-debug --force
確認ポイント:
docker compose psでappがUpになっているphp -mにxdebugが表示されるcode --list-extensionsでxdebug.php-debugが表示される
ここで詰まる場合は、7章のトラブルシュートを先に確認してください。
3. PHPコンテナでXdebugを有効化する
docker/php/conf.d/xdebug.ini を作成します。
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_host=host.docker.internal
xdebug.client_port=9003
xdebug.log=/tmp/xdebug.log
次に、compose.yml を次の内容に更新します。
services:
app:
build:
context: .
dockerfile: docker/php/Dockerfile
working_dir: /var/www/html
volumes:
- ./:/var/www/html
- ./docker/php/conf.d/xdebug.ini:/usr/local/etc/php/conf.d/99-xdebug.ini:ro
extra_hosts:
- "host.docker.internal:host-gateway"
command: ["php", "-S", "0.0.0.0:8080", "-t", "/var/www/html/public"]
ports:
- "8080:8080"
compose.yml の変更反映では再ビルドは不要です。docker compose up -d で再作成して確認します。
docker compose up -d
docker compose exec app php -m | grep -i xdebug
docker compose exec app php -i | grep -E "xdebug.mode|xdebug.client_host|xdebug.client_port|xdebug.start_with_request|xdebug.log"
ポイント:
php -iは CLI 設定確認の近道です。最終的に止まるかどうかは 5 章の HTTP アクセスで確認します。xdebug.iniをボリュームマウントしている場合は再起動(docker compose up -d/docker compose restart app)で反映できます。Dockerfileを変更した場合は再ビルド(docker compose up --build -d)が必要です。
4. VS Code の launch.json を設定する
.vscode/launch.json を作成します。
{
"version": "0.2.0",
"configurations": [
{
"name": "Listen for Xdebug",
"type": "php",
"request": "launch",
"port": 9003,
"pathMappings": {
"/var/www/html": "${workspaceFolder}"
}
}
]
}
pathMappings は灰色ブレークポイント対策の要点です。
上記ではコンテナ側の実パス(remoteRoot)/var/www/html を、ローカル側(localRoot)${workspaceFolder} に対応づけています。
止まるまでの向きを図にすると、次のようになります。ブラウザの HTTP アクセスがきっかけになり、PHP コンテナ内の Xdebug が host.docker.internal:9003 経由で VS Code の待受へ接続します。
sequenceDiagram
participant Browser
participant PHP as PHP container
participant Xdebug
participant Host as host.docker.internal
participant VSCode as VS Code
Browser->>PHP: GET /index.php
PHP->>Xdebug: start debug session
Xdebug->>Host: connect to port 9003
Host->>VSCode: forward to PHP Debug listener
VSCode-->>Xdebug: breakpoint and step commands
Xdebug-->>PHP: pause and resume execution
PHP-->>Browser: HTTP response
xdebug.ini、launch.json、pathMappings のどこか 1 つでも向きがずれると、「CLI では設定が見えているのに HTTP で止まらない」状態になります。
VS Code 側の操作:
Run and Debugを開く- 構成で
Listen for Xdebugを選ぶ - 構成が選択できることを確認する(待受開始は 5 章で実施)
5. 最小サンプルでブレークポイント確認
public/index.php を作成します。
<?php
declare(strict_types=1);
$userId = 42;
$message = 'Xdebug connected';
// ここにブレークポイント
if ($userId > 0) {
echo $message . ' user=' . $userId . PHP_EOL;
} else {
echo 'invalid user' . PHP_EOL;
}
操作順を固定して実行します。
public/index.phpを保存する- VS Code で
Listen for Xdebugを開始する

- ブレークポイントが赤く有効になっていることを確認する

- ブラウザで
http://localhost:8080/index.phpを開く(または下記curl) - 停止したら
Step Overで進める
curl の場合:
curl http://localhost:8080/index.php
成功判定:
- ブレークポイント行で停止する
- Variables で
$userId/$messageを確認できる Step Overで次行へ進める
止まらない場合は 7 章へ進んでください。
6. start_with_request=yes から trigger へ移行する(任意)
常時デバッグを避けたい場合は、xdebug.ini の1行だけ変更します。
-xdebug.start_with_request=yes
+xdebug.start_with_request=trigger
反映:
docker compose restart app
docker compose exec app php -i | grep -E "xdebug.start_with_request"
主線のトリガー方法(クエリ):
curl "http://localhost:8080/index.php?XDEBUG_TRIGGER=1"
trigger に変更した後、トリガーなしアクセスで止まらないのは正常です。
7. よくある詰まりと復旧手順
| 症状 | まず確認すること | よくある原因 | 対処 |
|---|---|---|---|
| ブレークポイントで止まらない | docker compose exec app php -i で xdebug.mode / xdebug.start_with_request / xdebug.client_port を確認 | start_with_request=trigger のままトリガーなしでアクセスしている / client_port 不一致 | まず start_with_request=yes に戻して疎通確認。port: 9003 と合わせる |
| ブレークポイントが灰色 | launch.json の pathMappings と、コンテナ実パスを確認 | /var/www/html と ${workspaceFolder} の対応ズレ | pathMappings を "/var/www/html": "${workspaceFolder}" に修正 |
接続不可(client_host 解決失敗) | docker compose exec app getent hosts host.docker.internal | 名前解決できていない / extra_hosts 未設定 | extra_hosts: ["host.docker.internal:host-gateway"] を設定して docker compose up -d |
| VS Code側で待受していない | Run and Debug で Listen for Xdebug 実行中か確認 | 設定ミスではなく待受未開始 | Listen for Xdebug を開始してから再アクセス |
トラブル時の再確認コマンド:
docker compose ps
docker compose exec app php -i | grep -E "xdebug.mode|xdebug.client_host|xdebug.client_port|xdebug.start_with_request|xdebug.log"
docker compose exec app getent hosts host.docker.internal
docker compose exec app tail -f /tmp/xdebug.log
8. まとめと次の一歩
次の状態が整いました。
- 新規デモ環境で Xdebug ステップ実行を再現できる
xdebug.ini/launch.json/pathMappingsの最小構成を固定できるyes主線からtriggerへ任意移行できる
次の一歩:
- VS Codeで始めるPHP開発環境(推奨拡張 + settings.json最小構成) でエディタ基盤を再確認する
- VS CodeでPHPコード整形をそろえる(EditorConfig + PHP CS Fixer最小導入) で整形手順を固定する
- 実アプリ側の CRUD 実装で、Xdebug を使った調査手順に発展させる