This article describes the steps you need to do to debug WordPress PHP code that is running inside a Docker container. The instructions here are tested to work with a Docker container based on wordpress:php7.4-fpm-alpine image. For other images YMMV when following these instructions (esp. the part where we install Xdebug)
The first step is to install Xdebug which is PHP’s debugger. Do this by running following from inside the Docker container ref (Do not install Xdebug using apk add
or you will run into issues ):
apk --no-cache add pcre-dev ${PHPIZE_DEPS} \
&& pecl install xdebug \
&& docker-php-ext-enable xdebug \
&& apk del pcre-dev ${PHPIZE_DEPS}
This will do following things:
- build and install Xdebug (v3.0.2 at time of this writing) under
/usr/local/lib/php/extensions/no-debug-non-zts-20190902/xdebug.so
- create a
/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
file with just following line in it:
zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20190902/xdebug.so
You can now check if Xdebug is installed successfully by running:
bash-5.0# php -v
PHP 7.4.4 (cli) (built: Mar 24 2020 01:34:16) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
with Xdebug v3.0.2, Copyright (c) 2002-2021, by Derick Rethans
with Zend OPcache v7.4.4, Copyright (c), by Zend Technologies
If you want to see all the ini
files that PHP loads, you can do that by running:
Now to enable remote debugging add following lines to docker-php-ext-xdebug.ini
:
xdebug.mode = debug
xdebug.start_with_request = yes
xdebug.client_port = 9000
xdebug.remote_handler=dbgp
xdebug.client_host=host.docker.internal
xdebug.idekey=VSCODE
xdebug.log=/usr/local/etc/php/xdebug.log
If the log file does not exist one will be created at time of debugging. But it gets created with root
as its owner and is inaccessible to the www-data
user which is the user php-fpm
runs as. So you might as well create the file and chown
the owner to www-data
.
Refer this page for an explanation of the settings.
Install PHP debug extension for VS Code. After installing the extension, create or open existing launch.json
and add following section to it:
{
"name": "Listen for XDebug",
"type": "php",
"request": "launch",
"port": 9000,
"log": true,
"externalConsole": false,
"pathMappings": {
"/var/www/html": "${workspaceRoot}/www-html",
},
"ignore": [
"**/vendor/**/*.php"
]
}
The pathMappings
is used to map code inside the Docker container to code stored locally. Correct it as appropriate in your case. The port
should match the port declared in xdebug.client_port
.
Now run VS Code in debug mode with above configuration. The blue ribbon should turn orange and you will be able to set breakpoints.
Next, we need to restart the php-fpm
process for xdebug settings in docker-php-ext-xdebug.ini
to take effect. I do this by just restarting the container. An alternate way – one that I haven’t tried – is to run this from inside the container:
Now you can make a request and the VS Code debugger should break!
You might be wondering two things:
- we have
php-fpm
running on port 9000 in our Docker container. Then how come we can use same port in xdebug.client_port
? - we did not have to publish the port. How come VS Code is able to connect to Xdebug?
The answer is that it works because Xdebug is the client and it is VS Code that is the server in this setup!
If you don’t have VS Code running you will see following errors in Docker log because Xdebug is not able to connect to VS Code:
NOTICE: PHP message: Xdebug: [Step Debug] Could not connect to debugging client. Tried: host.docker.internal:9000 (through xdebug.client_host/xdebug.client_port) 😦
Comment out the xdebug
settings (i.e., turn xdebug
off) when VS Code is not running to avoid the errors.