Using and configuring XDebug since the release of version 3 has been a breeze. Similarly, getting XDebug to work when using a Docker Container as a dev environment is equally easy. Follow these steps.
1. Add the installation commands in your Dockerfile
The first step is to install the xdebug module for PHP in the Docker Container. You can do that in the the Dockerfile for the container by adding the following lines (assume lines before and lines after this snippet):
&& pecl install xdebug \
&& docker-php-ext-enable xdebug \
2. Update docker-compose.yml
If you are using docker-compose.yml
, you will also need to add the following lines to add the internal host, and to set the xdebug environment variables:
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
XDEBUG_MODE: develop,debug
XDEBUG_CONFIG:
client_host=host.docker.internal
start_with_request=yes
3. Update your container’s PHP configuration files
Inside your container’s php.ini
file (or docker-php-ext-xdebug.ini
, if you have it), add the following lines:
[xdebug]
zend_extension=xdebug
xdebug.mode=develop,debug
xdebug.start_with_request=yes
xdebug.remote_port=9003
xdebug.client_port=9003
xdebug.remote_host=host.docker.internal
4. Start your container and test to make sure everything works
Create a file named xdebug_info.php
in your container’s document root, and the following lines to it:
<?php
xdebug_info();
Start your container and visit it in your browser, loading xdebug_info.php
. You should see that XDebug is now correctly installed.
5. Setup VSCode to properly connect to XDebug
As a first step, you will need to install a PHP debugging plugin in VSCode. I recommend PHP Debug
from the XDebug developers. It’s easy to setup and works very well. You can install it through the plugin tab in VSCode. The plugin repository is here: https://github.com/xdebug/vscode-php-debug.
Next, click the Debug icon in the left sidebar, then under ‘Run’ from the main menu, select ‘Add configuration’. Adjust the launch
section of your settings to look like this. Note, adjust the pathMappings
entry to match your setup. The ${workspaceFolder}
references the folder you open in VSCode. The path on the left side is the path to that folder inside the Docker container.
"launch": {
"configurations": [
{
"name": "Listen for Xdebug",
"type": "php",
"request": "launch",
"port": 9003
},
{
"name": "Listen on Docker for Xdebug",
"type": "php",
"request": "launch",
"port": 9003,
"pathMappings": {
"/var/www": "${workspaceFolder}"
}
},
]
}
6. Select a project and debug a file
Open a project folder, and load a file into the editor. In the editor, click beside the line number where you want XDebug to make its first stop and add a breakpoint. A red dot should appear.
Now, click the Debug icon in the left sidebar. At the top of the sidebar, you should now see the debug options you added to your settings file. Select the ‘Listen on Docker for Xdebug’ option, then click the little green arrow beside it.
When XDebug is active, the status bar at the bottom of the editor should become orange. As well, the XDEbug control applet should appear at the top of the editor window.
Because you have setup XDebug to Open With Request
you can now simply load your page into your browser. In the editor, you will see script execution stop at your breakpoint, and you can now inspect all breakpoints, the call stack, SuperGlobals, constants and more.
Use the XDebug applet at the top of the editor pane to navigate through your code, stepping over, into or out of functions as you need to.
Addendum
I have discovered through use (and errors, of course), that the pathMappings
in your launch.json
config are very important. They default above show a path mapping to /var/www
on the docker host. In most cases, however, I tend to open the project folder alone in VSCode, not the base Docker shared folder. If the folder you open in VSCode does not match your pathMappings
, then XDebug will freeze any and all PHP scripts until you either quit and/or resolve the issue. For me, that meant pathMappings
like this:
"pathMappings": {
"/var/www/code": "${workspaceFolder}"
}
I hope this saves you some of the issues I ran into trying to figure this out.