Skip to content

Instantly share code, notes, and snippets.

Last active May 13, 2024 15:30
Show Gist options
  • Save antfroger/1f2b24fdba0f215a41c8a94e8aa062f7 to your computer and use it in GitHub Desktop.
Save antfroger/1f2b24fdba0f215a41c8a94e8aa062f7 to your computer and use it in GitHub Desktop.
Using xdebug with Windows 10, WSL2, Docker and VS Code

Configuring xdebug to work with Windows 10 (WSL2), Docker and VS Code

Configuring your dev environment to be able to use xdebug when you're working on Windows 10 (with WSL2) and Docker with VS Code can be (a bit) tricky.
This is a quick reminder of how I've done that.

Configuring the environment

  1. Install and configure xdebug in Docker

    # Install xdebug according to the Docker image you're using
    RUN pecl install xdebug
    COPY xdebug.ini  $PHP_INI_DIR/conf.d/

    (cf. the xdebug.ini file in this gist)

  2. Setup VS Code

    PHP Debug is the extension to debug PHP in VS Code.
    Once installed and your project opened, create the configuration file .vscode/lauch.json
    (cf. the lauch.json file in this gist)

    Two impostant things here :

    • The port must match the one defined in xdebug.ini
    • pathMappings must associate the path of your app on Docker and the path of your VSCode project
      (do not use an absolute or relative path. You must use the variables VSCode provides)
  3. Configure Windows Defender Firewall

    Even after starting debugging, breakpoints might never be hitten. That's because of Windows Defender Firewall.
    It treats WSL as a public network by default and blocks access. This can be fixed by adding a rule. Just run (with Powershell):

    New-NetFirewallRule -DisplayName "WSL" -Direction Inbound  -InterfaceAlias "vEthernet (WSL)"  -Action Allow

    More about this issue here

Debug a request

Now that your environment is set up, it's time to debug!

  1. Run a debugging session

    In the left side panel of VSCode, select the "Debug view" (or just press Ctrl + Shift + D), make sure that the chosen configuration is the one you added in the file lauch.json. Then click on the little green triangle titled "Start debugging".

  2. Add breakpoints wherever you want to debug your app

  3. Refresh your browser!

You can add Xdebug helper to debug in Chrome.

You're ready to create an awesone app!

Want to know more on debugging with xdebug?
Let's read the 'Step Debugging' doc

"version": "0.2.0",
"configurations": [
"name": "Listen for XDebug",
"type": "php",
"request": "launch",
// I changed the port, by default xdebug 3 uses 9003
"port": 5902,
"pathMappings": {
"/var/www/my-app": "${workspaceFolder}"
"hostname": "localhost"
xdebug.client_port=5902 #same port as in launch.json
#Uncomment this line to enable xdebug for each request
Copy link

StefanRickli commented Jul 20, 2023

I've followed all the steps as well, but it is not working for me. The xdebug logs looks good, but not errors, nor warnings at all.

[18] Log opened at 2022-05-16 05:49:07.140566
[18] [Step Debug] INFO: Connecting to configured address/port: host.docker.internal:5902.
[18] [Step Debug] INFO: Connected to debugging client: host.docker.internal:5902 (through xdebug.client_host/xdebug.client_port). :-)
[18] [Step Debug] -> <init xmlns="urn:debugger_protocol_v1" xmlns:xdebug="" fileuri="file:///var/www/html/webroot/info.php" language="PHP" xdebug:language_version="7.4.19" protocol_version="1.0" appid="18"><engine version="3.1.4"><![CDATA[Xdebug]]></engine><author><![CDATA[Derick Rethans]]></author><url><![CDATA[]]></url><copyright><![CDATA[Copyright (c) 2002-2022 by Derick Rethans]]></copyright></init>

[18] [Step Debug] <- feature_set -i 1 -n resolved_breakpoints -v 1
[18] [Step Debug] -> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="" command="feature_set" transaction_id="1" feature="resolved_breakpoints" success="1"></response>

[18] [Step Debug] <- feature_set -i 2 -n notify_ok -v 1
[18] [Step Debug] -> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="" command="feature_set" transaction_id="2" feature="notify_ok" success="1"></response>

[18] [Step Debug] <- feature_set -i 3 -n extended_properties -v 1
[18] [Step Debug] -> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="" command="feature_set" transaction_id="3" feature="extended_properties" success="1"></response>

Increase the Xdebug loglevel to 10 (xdebug.log_level = 10). Then you see how it compares the file paths. Maybe your path mapping is misconfigured.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment