44

I'm trying to debug a PHP app running on Docker with VSCode, but without success.

In the past I was able to easily debug my PHP apps with VSCode running WAMP Server, but since I started working with Docker I'm unable to get debug working. Searched for several tutorials online, checked some threads here on StackOverflow (ex.: Docker and XDebug not reading breakpoints VSCode), but I'm still not able to get this working.

Dockerfile:

FROM php:7.1.8-apache

COPY /cms /srv/app/cms
COPY .docker/cms/vhosts/vhost.conf /etc/apache2/sites-available/cms.conf
COPY .docker/cms/vhosts/vhost-ssl.conf /etc/apache2/sites-available/cms-ssl.conf
COPY .docker/cms/vhosts/certificate.conf /etc/ssl/certs/certificate.conf
COPY .docker/cms/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini

WORKDIR /srv/app/cms

RUN docker-php-ext-install mbstring pdo pdo_mysql
RUN pecl install xdebug 
RUN docker-php-ext-enable xdebug
RUN chown -R www-data:www-data /srv/app/cms
RUN openssl req -x509 -new -out /etc/ssl/certs/ssl-cert-cms.crt -config /etc/ssl/certs/certificate.conf
RUN a2ensite cms.conf
RUN a2ensite cms-ssl.conf
RUN a2enmod rewrite
RUN a2enmod ssl

xdebug.ini

[xdebug]
xdebug.default_enable=1
xdebug.remote_enable=1
xdebug.remote_port=9000
xdebug.remote_connect_back=0
xdebug.remote_host='host.docker.internal'
xdebug.idekey='VSCODE'
xdebug.remote_autostart=1

docker-compose.yml

version: '3.7'
services:
cms:
  build:
    context: .
    dockerfile: .docker/cms/Dockerfile
  image: php:7.1.8-apache
  ports:
    - 18080:80
    - 14430:443
  volumes:
    - ./cms:/srv/app/cms
  links:
    - mysql
    - redis
  environment:
    DB_HOST: mysql
    VIRTUAL_HOST: my.app.localhost
    PHP_EXTENSION_XDEBUG: 1

VSCode: launch.json

"configurations": [
    {
        "name": "Listen for XDebug",
        "type": "php",
        "request": "launch",
        "pathMappings": {
           "/srv/app/cms": "${workspaceRoot}/my.app/cms",
        },
        "port": 9000
    }, {
        "name": "Launch currently open script",
        "type": "php",
        "request": "launch",
        "program": "${file}",
        "cwd": "${fileDirname}",
        "port": 9000
    }
]

When I debug the app no breakpoint is being triggered. What am I doing wrong?

UPDATE: Based on some suggestions i've updated my docker-compose.yml and my launch.json files but nothing changed.

docker-compose.yml

ports:
  - 18080:80
  - 14430:443
  - 9000:9000 //added new xdebug default port

launch.json

"configurations": [
    {
        "name": "Listen for XDebug",
        "type": "php",
        "request": "launch",
        "pathMappings": {
           "/srv/app/cms": "${workspaceRoot}/my.app/cms",
        },
        "port": 9000,
        "log": true
    }
]

VSCode Debug Console:

<- launchResponse
Response {
seq: 0,
type: 'response',
request_seq: 2,
command: 'launch',
success: true }

UPDATE #2: Removed the Xdebug port (9000) from the docker-compose.yml settings. Here is the xdebug log result:

Log opened at 2018-09-30 22:21:09 I: Connecting to configured address/port: host.docker.internal:9000. E: Time-out connecting to client (Waited: 200 ms). :-( Log closed at 2018-09-30 22:21:09

Log opened at 2018-09-30 22:21:17 I: Connecting to configured address/port: host.docker.internal:9000. E: Time-out connecting to client (Waited: 200 ms). :-( Log closed at 2018-09-30 22:21:17

Log opened at 2018-09-30 22:21:18 I: Connecting to configured address/port: host.docker.internal:9000. E: Time-out connecting to client (Waited: 200 ms). :-( Log closed at 2018-09-30 22:21:18

Log opened at 2018-09-30 22:21:18 I: Connecting to configured address/port: host.docker.internal:9000. E: Time-out connecting to client (Waited: 200 ms). :-( Log closed at 2018-09-30 22:21:18

Any more suggestions?

Zoe
  • 27,060
  • 21
  • 118
  • 148
Ricky
  • 2,912
  • 8
  • 47
  • 74
  • 1) So .. what Xdebug log has to say about it? Show it. 2) What's your host OS? – LazyOne Sep 30 '18 at 16:31
  • @LazyOne the only output i get in the debug console is this: <- launchResponse Response { seq: 0, type: 'response', request_seq: 2, command: 'launch', success: true } – Ricky Sep 30 '18 at 21:20
  • No -- Xdebug's own log, not VSCode. See https://xdebug.org/docs/all_settings#remote_log – LazyOne Sep 30 '18 at 21:31
  • You do not need to expose xdebug port .. as it's Xdebug connects to VSCode and NOT other way around. RTM please. – LazyOne Sep 30 '18 at 21:32
  • @LazyOne i've removed the xdebug port from the docker-compose settings and added the xdebug log result to my question. – Ricky Sep 30 '18 at 22:28
  • 1
    As you can see from the log .. it cannot establish connection with VSCode. It could be: 1) wrong host (but `host.docker.internal` should be OK). Maybe try platform specific name; 2) Firewall on you host OS (make sure that VSCode can listen on any interface etc); 3) VSCode is not listening (you have not specific your host OS ... so I cannot suggest specific command, but in general -- `netstat`). Make sure it's VSCode that listens on TCP 9000 port; 4) Docker networking (does not allow connection leave Docker containers/network). – LazyOne Sep 30 '18 at 22:57
  • 1
    A thousand thanks been trying to get this work since 3 days. – Pradyumna Challa Nov 29 '18 at 20:35

6 Answers6

29

Managed to solve my issue with the following settings:

launch.json

{
    "version": "0.2.0",
    "configurations": [{
            "name": "Listen for XDebug",
            "type": "php",
            "request": "launch",
            "port": 9000,
            "log": true,
            "externalConsole": false,
            "pathMappings": {
                "/srv/app/cms": "${workspaceRoot}/cms",
            },
            "ignore": [
                "**/vendor/**/*.php"
            ]
        },
    ]
}

xdebug.ini

zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20160303/xdebug.so
xdebug.default_enable=1
xdebug.remote_enable=1
xdebug.remote_port=9000
xdebug.remote_handler=dbgp
xdebug.remote_connect_back=0
xdebug.remote_host=host.docker.internal
xdebug.idekey=VSCODE
xdebug.remote_autostart=1
xdebug.remote_log=/usr/local/etc/php/xdebug.log
Ricky
  • 2,912
  • 8
  • 47
  • 74
7

Since xdebug version 3 there are breaking changes in config names.

My current working dockerfile:

RUN apt-get update; \
        apt-get -y --no-install-recommends install \
            php7.4-dev \
            php-pear \
            libcurl3-openssl-dev \
            libmcrypt-dev \
            libxml2-dev \
            libpng-dev \
        ; \
        pecl install xdebug; \
        { \
            echo "[xdebug]"; \
            echo "zend_extension=$(find /usr/lib/php/ -name xdebug.so)"; \
            echo "xdebug.mode=debug"; \
            echo "xdebug.start_with_request=yes"; \
            echo "xdebug.client_host=host.docker.internal"; \
            echo "xdebug.client_port=9001"; \
        } >> /etc/php/7.4/mods-available/xdebug.ini; \
        phpenmod -v 7.4 xdebug; \

VSC debug config:

    "configurations": [
        {
            "name": "XDebug (Docker)",
            "type": "php",
            "request": "launch",
            "port": 9001,
            "pathMappings": {
                "/var/www/app": "${workspaceRoot}",
            }
        }
    ]

More info: https://xdebug.org/docs/upgrade_guide

GetoX
  • 4,225
  • 2
  • 33
  • 30
4

Well, I have tried all the above answers and have spend hours but got not success because in all the above answer some concepts were not clear to new x-debug user just like me. I wish that I would have know the following concepts before starting setting up x-debugger, running on a docker container or a remote server, with my VS Code's PHP Debug. I am sure this will help searching for the solution of such issue.

X-Debug Settings

I was not certain that if my machine should be considered as client host or server host, though it was obvious but when you have spent hours on configurations then simple things started to get tricky ones.

xdebug.client_host

According to X-debug Docs:

This address should be the address of the machine where your IDE or debugging client is listening for incoming debugging connections.

I think, with the above piece of text needs no explanation. Hence, setup it up as follows in our x-debug configurations i.e. xdebug.ini:

xdebug.client_host=host.docker.internal

xdebug.remote_host

This was a bit tricky config to me. Actually there is no such configurations for x-debug but I kept thinking about it. :-)

PHP-Debug Settings

hostname

I had been using different configurations except this one (as in this thread no one had mentioned this) :-) and there was no success. I then re-explored the docs of PHP Debug came to know that it must get set to localhost in my case, and gave it a try, and boom! It worked!

"hostname": "localhost"

port

The should be set same as the xdebug.client_port and default value is 9300. Repeatedly mentioned in above answers.

pathMappings

This is an other really important config when trying to setup a docker server with your VS Code PHP Debug. It is an object and must map your local directory structure to the server/container directory i.e. /home/user/proj/html: ${workspaceRoot}. I can't further explain it, it did worked for me and I have mentioned it here. I will welcome if someone explain it.

Here are my final settings:

enter image description here

enter image description here

Hope this will help and save your hours :-)

Khuram
  • 1,820
  • 1
  • 26
  • 33
1

you are missing port :9000 (or :9001) in the docker-compose.yml,

which needs to be connectable, for the IDE to connect from the outside.

for VSCode the PHP Debug extension might be required to interact with xdebug.

the default launch.json only uses port: 9000 only once - and has log: true.

{
  "configurations": [{
      "name": "Listen for XDebug",
      "type": "php",
      "request": "launch",
      "port": 9000,
      "log": true
    }, {
      "name": "Launch",
      "request": "launch",
      "type": "php",
      "program": "${file}",
      "cwd": "${workspaceRoot}",
      "externalConsole": false
    }
  ]
}

also see vscode-php-debug and starting the debugger.

Martin Zeitler
  • 1
  • 19
  • 155
  • 216
  • 3
    *"which needs to be connectable, for the IDE to connect from the outside."* Interesting theory... What about checking Xdebug docs where it clearly says that it's Xdebug that connects to debug client (VSCode in this case) and NOT other way around? So it's not incoming connection (like it's for HTTP(s)) but **outgoing** and needs no mappings – LazyOne Sep 30 '18 at 19:48
  • @LazyOne in case "listening for remote connections" is required (possibly even "connecting back"), the container would need to expose the port. probably with `xdebug.remote_connect_back=1`... xdebug needs to run inside the container. – Martin Zeitler Sep 30 '18 at 20:05
  • it reads: `the port to which xdebug tries to connect on the remote host.` (which in this case is a container, similar to a remote host or virtual machine). – Martin Zeitler Sep 30 '18 at 20:11
  • 1
    Could you please clarify that? It's VSCode that listens on Xdebug port (locally, where it is running) and Xdebug does not listen anything, it does not accept any connections as it only sends them out. https://xdebug.org/docs/remote#communication – LazyOne Sep 30 '18 at 20:12
  • 4
    Xdebug (run in Docker container/VM) tries to connect to IDE (so it's outgoing connection). You do not need to expose that port in Docker (because it's for incoming connections). If you expose xdebug port in Docker .. then IDE will not be able to listen for incoming connection ... as port will be occupied by Docker. Firewall inside container or something like that (to enable outgoing connection) -- yes, if you have such thing .. but exposing .. for IDE to connect to Xdebug -- nope. **P.S.** I'm not touching any VSCode configs here as I'm not using it myself. – LazyOne Sep 30 '18 at 20:15
  • I followed the suggestion but it still doesn't work. Updated my question. – Ricky Sep 30 '18 at 21:31
1

XDEBUG v3 example for Symfony

enter image description here

docker-compose.yml:

###> XDEBUG 3 ###
# Use your client IP here
# Linux: run "ip a | grep docker0"
# Windows (with WSL2): Run "grep nameserver /etc/resolv.conf  | cut -d ' ' -f2"
# MacOS: host.docker.internal
###< XDEBUG 3 ###
environment:
  XDEBUG_CLIENT_HOST: 172.17.0.1
  XDEBUG_CLIENT_PORT: 9003
  PHP_IDE_CONFIG: serverName=Docker
volumes:
  - ./xdebug.ini:/usr/local/etc/php/conf.d/xdebug.ini

xdebug.ini

xdebug.mode=debug,coverage
xdebug.start_with_request=yes
xdebug.client_host=${XDEBUG_CLIENT_HOST}
xdebug.client_port=${XDEBUG_CLIENT_PORT}

xdebug.ini for php:7.2-fpm-alpine3.8

zend_extension=xdebug.so

[xdebug]
xdebug.cli_color = 1
xdebug.mode = debug
xdebug.start_with_request = yes
xdebug.discover_client_host = 0
xdebug.client_host=host.docker.internal
xdebug.ideKey=docker

Example config vscode modify pathMappings

launch.json:

{

    "version": "0.2.0",
    "configurations": [{
        "name": "Listen for XDebug",
        "type": "php",
        "request": "launch",
        "port": 9003,
        "log": true,
        "externalConsole": false,
        "pathMappings": {
            "/appdata/www": "${workspaceRoot}/api",
        },
        "ignore": [
            "**/vendor/**/*.php"
        ]
    },
]
}
maccevedor
  • 155
  • 2
  • 5
1

For everyone running on the following stack:

  • Ubuntu
  • XDebug 3
  • Laravel Sail

docker/8.0/php.ini

[xdebug]
xdebug.discover_client_host=true
xdebug.start_with_request=yes 

.env

SAIL_XDEBUG_MODE=develop,debug
# For linux only:
# you may read up about how to get the ip here: https://laravel.com/docs/8.x/sail#debugging-with-xdebug
SAIL_XDEBUG_CONFIG="client_host=172.22.0.1"

launch.json

{
"version": "0.2.0",
"configurations": [
    {
        "name": "Listen for XDebug via Docker",
        "type": "php",
        "request": "launch",
        "port": 9000,
        "log": true,
        "externalConsole": false,
        "pathMappings": {
            "/var/www/html": "${workspaceRoot}/www",
        },
        "ignore": [
            "**/vendor/**/*.php"
        ]
    },
] }
Sylver11
  • 129
  • 1
  • 8