phpdockerwebserverxdebugxdebug-3

Configure Xdebug in Docker container


I'm trying to create a docker container with PHP and Xdebug to use step debugging. I use VSCode and somehow this debugger it's not working.

Apparently the Dockerfile is not been executed when I use docker compose up -d command. I assume that is because in the file it has a COPY command to copy a file (called 90-xdebug.ini) from my project to a specific directory. And after the container is up, I check the directory and the file isn't there... then I have to execute the commands in Dockerfile manually.

Anyways, after installing, I know that the installation worked because the xdebug_info() function works. But I don't know why VSCode can't debug it.

My OS is Ubuntu 20.04.5 LTS; Dockerfile, docker-compose.yml and 90-xdebug.ini are in project's root.

My Dockerfile:

FROM php:7.4-apache

COPY 90-xdebug.ini "/usr/local/etc/php/conf.d"
RUN pecl install xdebug
RUN docker-php-ext-enable xdebug

90-xdebug.ini:

xdebug.mode=debug
xdebug.discover_client_host=0
xdebug.client_host=host.docker.internal

docker-compose.yml:

services:
  php-apache:
    container_name: php-apache
    image: php:7.4-apache
    build:
      context: .
      dockerfile: Dockerfile
    extra_hosts:
      - "host.docker.internal:host-gateway"
    volumes:
      - ./:/var/www/html/
    working_dir: /var/www/html/
    ports:
      - 3003:3003
    entrypoint: "php -S 0.0.0.0:3003"

launch.json inside ".vscode" directory:

{
    // 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
        },
        {
            "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"
            }
        }
    ]
}

Extra information: this is my program and i've put a break point on "$var = "txt1" " line, but it runs directly towards "xdebug_info()"

<?php

function fprint(string $str):void{
    echo $str;
}

$var = "txt1";
fprint($var);

$var = "txt2";
fprint($var);

$var = "txt3";
fprint($var);
// echo $PHP_INI_DIR;
// echo phpinfo();
xdebug_info();

Solution

  • As you say (in a comment) that xdebug_info() shows that you had an active debugging connection, then that means that the debugger works. What is likely happening here is that:

    1. you don't have any breakpoints set - in which case the debugger never breaks

    2. more likely, that you do have a breakpoint set, but that you don't have a path mapping configured, that maps a path from inside the container (/var/www/html) to your local project route, which you can refer to with "${workspaceRoot}/html". You need to tell VS Code this path mapping by making the following configuration:

       "configurations": [
           {
               "name": "Listen for Xdebug",
               "type": "php",
               "request": "launch",
               "port": 9003,
               "pathMappings": {
                   "/var/www/html": "${workspaceRoot}/html",
               }
           },
      

      I might not have gotten the exact right paths in this configuration. If you tell Xdebug to make a log file (-dxdebug.log=/tmp/xdebug.log and -dxdebug.log_level=10) it will create a log file in your container, where the contents tell you which breakpoint file name is tried to be matched against the files that PHP sees, something like:

      [11] [Step Debug] DEBUG: I:
          Matching breakpoint '/home/caio/dev/project/html/info.php:1'
          against location '/var/www/html/info.php:2'.
      

      If these paths don't match, adjust your path mappings.