7

I've been working with VSCode + Docker in Windows for some years now, and managed to have a fully working dev environment without any issues.

Recently i setup a new development environment with WSL2. Moved all my projects, libraries, CLIs, etc, into WSL, using Docker Windows with WSL2 containers and VSCode on Windows with remote connection to WSL. Everything is working very smoothly and i like the fact i can have everything separated.

But recently i came across an issue that i'm unable to solve, i lost the ability to debug PHP files. I'm using VSCode Remote WSL extension to work on my projects inside WSL, but when i try to debug, nothing happens.

I have tree debugging settings in my VSCode for each dev environment that i use (Windows, MacOS and WSL). All work except for the WSL. When i try to debug with WSL, literally nothing happens, no output erros, no debug console information, nothing...

Here are my VSCode debug settings:

{
    "version": "0.2.0",
    "configurations": [{
            "name": "Listen for XDebug Win10",
            "type": "php",
            "request": "launch",
            "port": 9000,
            "log": true,
            "externalConsole": false,
            "pathMappings": {
                "/var/www/project-a/api": "\\\\wsl$\\Ubuntu\\home\\ubuntu\\PROJECTS\\project-a\\api",
            },
            "ignore": [
                "**/vendor/**/*.php"
            ]
        },
        {
            "name": "Listen for XDebug MacOS",
            "type": "php",
            "request": "launch",
            "port": 9000,
            "log": true,
            "externalConsole": false,
            "pathMappings": {
                "/var/www/project-a/api": "/Users/ricky/PROJECTS/project-a/api",
            },
            "ignore": [
                "**/vendor/**/*.php"
            ]
        },
        {
            "name": "Listen for XDebug WSL",
            "type": "php",
            "request": "launch",
            "port": 9000,
            "log": true,
            "externalConsole": false,
            "pathMappings": {
                "/var/www/project-a/api": "/home/ubuntu/PROJECTS/project-a/api",
            },
            "ignore": [
                "**/vendor/**/*.php"
            ]
        },
    ]
}

What am i doing wrong? Any ideas on how to solve this issue?

### UPDATE: I've changed the original right answer to a new one. Although @romain-prevost's solution worked, I think @dark's approach is wayyy much simpler :)

Ricky
  • 2,912
  • 8
  • 47
  • 74

3 Answers3

14

Forget about the other answers. They are working but too complicated in my opinion.

The problem is, that you can't connect to xdebug.

The solution is to tell xdebug to set remote_host to host.docker.internal. Everything from there is available to localhost. Now you only have to listen inside Visual Studio Code to localhost via hostname.

Et voilà. Now you can debug things invoked by your browser, inside your phpunit tests or within your commandline scripts.

Complete Example

launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for XDebug",
            "type": "php",
            "request": "launch",
            "port": 9000,
            "pathMappings": {
                "/var/www/html/": "${workspaceRoot}"
            },
            "hostname": "localhost"
        }
    ]
}

php.ini

[XDebug]
xdebug.remote_enable = 1
xdebug.remote_autostart = 1
xdebug.remote_host = host.docker.internal
xdebug.remote_port = 9000

Update for XDebug 3

launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for XDebug",
            "type": "php",
            "request": "launch",
            "port": 9003,
            "pathMappings": {
                "/var/www/html/": "${workspaceRoot}"
            },
            "hostname": "localhost"
        }
    ]
}

php.ini

[XDebug]
xdebug.mode = develop
xdebug.start_with_request = yes
xdebug.client_host = host.docker.internal
xdebug.client_port = 9003
Dark
  • 185
  • 1
  • 9
  • I'm going to test your approach in the following days and get back with feedback. – Ricky Sep 30 '20 at 06:46
  • 3
    I've changed the right answer to yours, It's wayyy simpler :) – Ricky Oct 20 '20 at 15:41
  • 2
    the key for me was to add the hostname key to the debug profile. The xdebug setup was not working on WSL2 because I needed to set up the debug listener on an IPV4 address. It turns out that this is one of the reasons that this key was added in the first place: https://github.com/felixfbecker/vscode-php-debug/issues/288 – IanAWP Nov 23 '20 at 13:26
  • What can be the solution to the same issue for golang project? – Ankush K Mar 14 '21 at 05:04
  • 1
    This was driving me insane for about two hours, but the "hostname": "localhost" in launch.json fixed it for me. At least I learned a lot about XDebug in the process. :-) – TWA Mar 18 '22 at 15:35
10

I have been struggling with PHP xdebug in Docker using WSL2 as well. It all comes down to the remote host.

What is your xdebug config in php.ini? You should set xdebug.remote_host to your WSL2 local IP address (which you can get in a terminal using hostame -I).

I have tried several times to set the remote host IP address in my Docker—composing a file to pass to the container on startup—but it always fails. Thanks to another StackOverflow answer, however, I have a solution for that too:

In WSL2, set an environment variable for your local IP in your .bashrc file. I have set mine to

export IP=$(hostname -I)

In your Docker compose file for the PHP service, pass the IP address as a new host with the extra_hosts key. For compose v3.2 it is

extra_hosts:
 - "docker.host:${IP}"

You can look here for other compose versions: https://docs.docker.com/compose/compose-file/

Finally, edit your php.ini file for xdebug to have this line:

xdebug.remote_host=docker.host

Your container will be able to reach the WSL2 distribution with your docker.host and connect to the port you set for xdebug.

I spent a lot of time figuring this out, mainly because WSL2 was released officially a few days ago and there are not many guides about it. It was not so complicated in the end, but without the extra_hosts key I could not get the WSL2 IP address to work. It was in the container and in xdebug config, but I always got an error about the resource being unavailable, so don't forget it

Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
  • you tha man! :D Never thought about the remote_host in php.ini, i had it pointing to my docker machine (xdebug.remote_host=host.docker.internal). Your solution was an easy one to do. Once again thanks and welcome to StackOverflow :) – Ricky May 31 '20 at 16:58
  • This no longer seems to work. The docker can't connect to the IP address of the WSL instance. Fortunately, host.docker.internal is working as it's sharing port 9000 with the host (windows) – Jonas Wouters Sep 25 '20 at 17:43
1

The answer by @Romain-prevost is definitely the easiest and best way. If for some reason you can't get that to work, there is another alternative.

host.docker.internal will likely be reachable from within your container, but is a 192.* address by default, and is your Windows-based Docker IP. So you would need to set up forwarding from your Windows host into your WSL2 instance. This is outlined in this script in this issue at Github/WSL. You would simply change the ports to 9000 in that script. You could also use WSL2-Host to have a named entry in your hosts file for that IP and modify the script further to both restrict calling/receiving IPs.

sorrell
  • 1,801
  • 1
  • 16
  • 27