VS Code PHP 调试器不适用于 Docker

VS Code PHP debugger does not work with Docker

我正在尝试使用 Docker 为 Windows 和 VS Code 设置开发环境以调试 PHP 代码。

我已经从这个 Docker 文件创建了一个 Docker 容器:

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

当我在 VS Code 上启动调试器并使用浏览器打开 PHP 文件时,即使我没有在 PHP 文件中放置任何断点,页面也会永远加载。

如果我在文件中放置一个断点,页面仍然会永远加载并且调试器不会在断点处停止:步骤 over/into/out 图标在 VS 代码和变量 table 上变灰是空的:

如果我停止 VS Code 上的调试器,页面加载成功。

这些是 Xdebug 的日志:

[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>

这是 VS Code 的 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"
            }
        }
    ]
}

我终于弄清楚为什么调试器不起作用:我在容器内启动调试会话(我通过 Remote - Containers VS Code extension 连接到它)而不是从 Docker 主机。因此,在这种情况下,xdebug.client_host 的正确值是 localhost,因为 Xdebug 客户端和服务器都在同一台主机上。

为了使其与 xdebug.client_host=host.docker.internal 一起使用,我设置了一个 Docker 卷并直接在 Windows 上启动了调试器,而没有从 VS Code 内部连接到容器。在这种情况下,我还必须在 launch.json 文件中添加路径映射,它将 Docker 卷的路径映射到工作区文件夹。