Search code examples
phpvisual-studio-codexdebugdocker-for-windows

VS Code PHP debugger does not work with Docker


I am trying to setup a development environment with Docker for Windows and VS Code to debug PHP code.

I have created a Docker container from this Dockerfile:

FROM php:8.0.10-apache

RUN pecl install xdebug-3.0.4 && \
    docker-php-ext-enable xdebug && \
    mkdir /var/log/php && \
    chown www-data:www-data /var/log/php && \
    chmod 755 /var/log/php && \
    { \
        echo ''; \
        echo '[xdebug]'; \
        echo 'xdebug.mode=develop,debug'; \
        echo 'xdebug.client_host=host.docker.internal'; \
        echo 'xdebug.start_with_request=yes'; \
        echo 'xdebug.log=/var/log/php/xdebug.log'; \
    } >> ${PHP_INI_DIR}/conf.d/docker-php-ext-xdebug.ini && \
    echo 'error_reporting=E_ALL' >> ${PHP_INI_DIR}/conf.d/error_reporting.ini

When I start the debugger on VS Code and open a PHP file with my browser, the page loads forever even when I don't put any breakpoint in the PHP file.

If I put a breakpoint in the file, the page still loads forever and the debugger does not stop on the breakpoint: step over/into/out icons are greyed out on VS code and the variables table is empty: VS Code screenshot

If I stop the debugger on VS Code, the page loads successfully.

These are Xdebug's logs:

[17] Log opened at 2021-09-16 10:39:03.887841
[17] [Step Debug] INFO: Connecting to configured address/port: host.docker.internal:9003.
[17] [Step Debug] INFO: Connected to debugging client: host.docker.internal:9003 (through xdebug.client_host/xdebug.client_port). :-)
[17] [Step Debug] -> <init xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" fileuri="file:///var/www/html/test.php" language="PHP" xdebug:language_version="8.0.10" protocol_version="1.0" appid="17"><engine version="3.0.4"><![CDATA[Xdebug]]></engine><author><![CDATA[Derick Rethans]]></author><url><![CDATA[https://xdebug.org]]></url><copyright><![CDATA[Copyright (c) 2002-2021 by Derick Rethans]]></copyright></init>

[17] [Step Debug] -> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" status="stopping" reason="ok"></response>

[17] Log closed at 2021-09-16 10:41:00.782334

[18] Log opened at 2021-09-16 10:41:10.195656
[18] [Step Debug] INFO: Connecting to configured address/port: host.docker.internal:9003.
[18] [Step Debug] INFO: Connected to debugging client: host.docker.internal:9003 (through xdebug.client_host/xdebug.client_port). :-)
[18] [Step Debug] -> <init xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" fileuri="file:///var/www/html/test.php" language="PHP" xdebug:language_version="8.0.10" protocol_version="1.0" appid="18"><engine version="3.0.4"><![CDATA[Xdebug]]></engine><author><![CDATA[Derick Rethans]]></author><url><![CDATA[https://xdebug.org]]></url><copyright><![CDATA[Copyright (c) 2002-2021 by Derick Rethans]]></copyright></init>

[19] Log opened at 2021-09-16 10:42:26.969063
[19] [Step Debug] INFO: Connecting to configured address/port: host.docker.internal:9003.
[19] [Step Debug] INFO: Connected to debugging client: host.docker.internal:9003 (through xdebug.client_host/xdebug.client_port). :-)
[19] [Step Debug] -> <init xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" fileuri="file:///var/www/html/test.php" language="PHP" xdebug:language_version="8.0.10" protocol_version="1.0" appid="19"><engine version="3.0.4"><![CDATA[Xdebug]]></engine><author><![CDATA[Derick Rethans]]></author><url><![CDATA[https://xdebug.org]]></url><copyright><![CDATA[Copyright (c) 2002-2021 by Derick Rethans]]></copyright></init>

[19] [Step Debug] -> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" status="stopping" reason="ok"></response>

[19] Log closed at 2021-09-16 10:42:31.116586

[20] Log opened at 2021-09-16 10:42:36.631851
[20] [Step Debug] INFO: Connecting to configured address/port: host.docker.internal:9003.
[20] [Step Debug] ERR: Time-out connecting to debugging client, waited: 200 ms. Tried: host.docker.internal:9003 (through xdebug.client_host/xdebug.client_port) :-(
[20] Log closed at 2021-09-16 10:42:36.835780

[21] Log opened at 2021-09-16 10:42:38.915095
[21] [Step Debug] INFO: Connecting to configured address/port: host.docker.internal:9003.
[21] [Step Debug] INFO: Connected to debugging client: host.docker.internal:9003 (through xdebug.client_host/xdebug.client_port). :-)
[21] [Step Debug] -> <init xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" fileuri="file:///var/www/html/test.php" language="PHP" xdebug:language_version="8.0.10" protocol_version="1.0" appid="21"><engine version="3.0.4"><![CDATA[Xdebug]]></engine><author><![CDATA[Derick Rethans]]></author><url><![CDATA[https://xdebug.org]]></url><copyright><![CDATA[Copyright (c) 2002-2021 by Derick Rethans]]></copyright></init>

[1049] Log opened at 2021-09-16 10:42:40.727353
[1049] [Step Debug] INFO: Connecting to configured address/port: host.docker.internal:9003.
[1049] [Step Debug] INFO: Connected to debugging client: host.docker.internal:9003 (through xdebug.client_host/xdebug.client_port). :-)
[1049] [Step Debug] -> <init xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" fileuri="file:///var/www/html/test.php" language="PHP" xdebug:language_version="8.0.10" protocol_version="1.0" appid="1049"><engine version="3.0.4"><![CDATA[Xdebug]]></engine><author><![CDATA[Derick Rethans]]></author><url><![CDATA[https://xdebug.org]]></url><copyright><![CDATA[Copyright (c) 2002-2021 by Derick Rethans]]></copyright></init>

and this is VS Code's launch.json:

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for Xdebug",
            "type": "php",
            "request": "launch",
            "port": 9003,
            "pathMappings": {
                "/var/www/html/": "${workspaceFolder}"
            }
        },
        {
            "name": "Launch currently open script",
            "type": "php",
            "request": "launch",
            "program": "${file}",
            "cwd": "${fileDirname}",
            "port": 0,
            "runtimeArgs": [
                "-dxdebug.start_with_request=yes"
            ],
            "env": {
                "XDEBUG_MODE": "debug,develop",
                "XDEBUG_CONFIG": "client_port=${port}"
            }
        },
        {
            "name": "Launch Built-in web server",
            "type": "php",
            "request": "launch",
            "runtimeArgs": [
                "-dxdebug.mode=debug",
                "-dxdebug.start_with_request=yes",
                "-S",
                "localhost:0"
            ],
            "program": "",
            "cwd": "${workspaceRoot}",
            "port": 9003,
            "serverReadyAction": {
                "pattern": "Development Server \\(http://localhost:([0-9]+)\\) started",
                "uriFormat": "http://localhost:%s",
                "action": "openExternally"
            }
        }
    ]
}

Solution

  • I have finally figured out why the debugger did not work: I launched the debug session inside the container (I connected to it through the Remote - Containers VS Code extension) and not from the Docker host. So, in this case, the correct value for xdebug.client_host is localhost, since both the Xdebug client and the server are on the same host.

    To make it work with xdebug.client_host=host.docker.internal, I had set up a Docker volume and I started the debugger directly on Windows, without connecting to the container from inside VS Code. In this case I also had to add a path mapping in the launch.json file, which maps the Docker volume's path to the workspace folder.