Xdebug a PHP docker container in VS Code
by bernt & torsten
This is the 2nd installment on debugging PHP applications running in a docker container with Xdebug on VS Code. You can find out how I set up a Docker Container for Apache + MySQL + PHP + Xdebug and Codeigniter on macOS using Docker. In this article, I will cover how you configure Xdebug for use with VS Code.
I am not going to beat around the bush, so here we go – to debug a PHP Docker container in Visual Studio Code, follow these steps:
- Install the PHP Debug extension in Visual Studio Code.
- In your Docker container, make sure Xdebug is installed and configured with the following settings in your
php.ini
file:
zend_extension=xdebug.so
xdebug.mode=develop,coverage,debug,profile
xdebug.idekey=docker
xdebug.start_with_request=yes
xdebug.log=/dev/stdout
xdebug.client_port=9003
xdebug.remote_host=host.docker.internal
In Visual Studio Code, create a launch configuration for debugging by opening the Debug panel (View > Debug
), clicking the gear icon and selecting PHP
. Add the following configuration to launch.json:
{
"version": "0.2.0",
"configurations": [
{
"name": "Listen for Xdebug on Docker",
"type": "php",
"request": "launch",
"port": 9003,
"pathMappings": {
"/var/www/html/": "${workspaceFolder}"
}
}
]
}
- Start the debugger by clicking the green play button in the Debug panel or by pressing.
F5
. - Set a breakpoint in your code by clicking in the gutter to the left of the line you want to break on.
- Request the PHP script you want to debug. This will trigger the breakpoint, and you can inspect variables, step through code, and more in the Debug panel.
- When you are done debugging, stop the debugger by clicking the red square button in the Debug panel, or by pressing
Shift + F5
.
So let’s break it down a bit, so you know what each line means in the config file.
php.ini
zend_extension=xdebug.so
xdebug.mode=develop,coverage,debug,profile
xdebug.idekey=docker
xdebug.start_with_request=yes
xdebug.log=/dev/stdout
xdebug.client_port=9003
xdebug.remote_host=host.docker.internal
- zend_extension=xdebug.so
A Zend extension hooks into “lower level” languages, and a single extension can be both a PHP and a Zend extension, despite being very uncommon it’s possible and Xdebug is a good example of it.
- xdebug.mode=develop,coverage,debug,profile
This setting controls which Xdebug features got enabled, according to the documentation the following values gets accepted:
- develop
Enables Development Helpers, including the overloaded var_dump().
- coverage
Enables Code Coverage Analysis to generate code coverage reports, mainly with PHPUnit.
- debug
Enables Step Debugging. This can be used to step through your code while it is running, and analyze values of variables.
- profile
Enables Profiling, with which you can analyze performance bottlenecks with tools like CacheGrind.
- xdebug.idekey=docker
Controls which IDE Key Xdebug should pass on to the debugging client or proxy. The IDE Key is only important for use with the DBGp Proxy Tool, although some IDEs are incorrectly picky as to what its value is. The default is based on the DBGP_IDEKEY environment setting. If it is not present, the default falls back to an empty string.
- xdebug.start_with_request=yes
The functionality starts when the PHP request starts, and before any PHP code getting executed. For example, xdebug.mode=trace and xdebug.start_with_request=yes starts a Function Trace for the whole request.
- xdebug.log=/dev/stdout
Configure Xdebug’s log file, but here, we are redirecting the log content to the default stdout of our container.
- xdebug.client_port=9003
The port to which Xdebug tries to connect on the remote host. Port 9003 is the default for both Xdebug and the Command Line Debug Client. As many clients use this port number, it is best to leave this setting unchanged.
xdebug.remote_host=host.docker.internal
is a configuration setting for the Xdebug PHP extension. This setting specifies the hostname that Xdebug should use when connecting to a remote debugger.
host.docker.internal
is a special hostname that resolves to the IP address of the host machine from within a Docker container. This allows Xdebug running in the Docker container to connect to a debugger running on the host machine, such as Visual Studio Code.
By setting xdebug.remote_host
to host.docker.internal
, Xdebug is able to establish a connection with the debugger on the host machine, allowing you to debug your PHP code running in the Docker container.
This setting is often used in development environments where the PHP code is running in a Docker container and the debugger is running on the host machine. It allows developers to take advantage of the benefits of containerization while still being able to debug their code in an integrated development environment (IDE).
launch.json VS Code
The launch.json file
{
"version": "0.2.0",
"configurations": [
{
"name": "Listen for Xdebug on Docker",
"type": "php",
"request": "launch",
"port": 9003,
"pathMappings": {
"/var/www/html/": "${workspaceFolder}"
}
}
]
}
- name
Indicates the name given to a configuration object.
- type
Indicates the underlying debugger getting used.
- request
Indicates whether the configuration is intended to launch the program or attach to an already running instance.
- port
Indicates the port on which to listen for Xdebug
- pathMappings
Indicates a mapping of server paths to local paths.
When using /var/www/html/ as key, VSCode knows that the files at the container are under that path, and by using the ${workspaceFolder} as value, VSCode knows that locally the project files are under the current opened directory.
Troubleshooting
If Xdebug is not working as expected, here are some common issues and solutions:
- Make sure Xdebug is installed and enabled in your Docker container. You can check this by running
php -m
and verifying thatXdebug
is listed among the modules. - Check if the
xdebug.so
file exists in the correct location in your Docker container. This file is usually located in/usr/lib/php/<php-version>/
. - Make sure the
xdebug.remote_host
setting in yourphp.ini
file is set tohost.docker.internal
. This is the hostname that will be used to connect from your local machine to the Docker container. - Ensure that the port specified in your launch configuration (
9000
in the example) is open and accessible from the Docker container. You may need to adjust the firewall settings on your machine to allow traffic on this port. - Make sure the path mappings in your launch configuration are correct. The
"/var/www/html"
value should match the root path of your application in the Docker container, while"${workspaceFolder}"
should match the local path on your machine where your code is stored.
If none of these solutions solve the issue, it may be helpful to consult the Xdebug documentation or seek assistance from the Xdebug community.
The Importance of Creativity After 60
As we age, the importance of maintaining cognitive health becomes increasingly clear. For...
Why It’s Important to Exercise When You’re Over 60
Many of us find ourselves in a pickle as the years pile up. Once reliable sidekicks, our...
A Poem: The Last Time
You never know when it will be,
The last time you ski down slopes of snow,