Configuring Xdebug with Docker Compose and IntelliJ on Ubuntu
Introduction
This tutorial explains how to set up Xdebug with Docker-compose when using IntelliJ for local development on Ubuntu.
The Docker Compose File
In your docker-compose.yml
file add the following:
# Other configuration omitted for brevity..
extra_hosts:
- host.docker.internal:host-gateway
# Other configuration omitted for brevity..
extra_hosts
The
extra_hosts
configuration makes the container aware of the Docker host's IP, allowing Xdebug to communicate back to your IDE, which is outside the container.The
extra_hosts
key allows you to add custom hostname-to-IP mappings for your container. Essentially, it modifies the container’s/etc/hosts
file to resolvehost.docker.internal
to a specific IP address.
Adding extra_hosts
to your docker-compose.yml
file is helpful for Xdebug to connect back to your IDE.
host.docker.internal
host.docker.internal
is a special DNS name provided by Docker to enable your container to access services running on the host machine (i.e., your computer or server that is running Docker).
This is useful when your container needs to communicate with the host, for example, for development purposes like debugging with Xdebug or accessing databases, APIs, or other services running locally on the host.
host-gateway
The
host-gateway
option is simpler and more reliable if your Docker version supports it (Docker 20.10+). It dynamically resolves the host's IP address without hardcoding it.
To summarize host.docker.internal:host-gateway
routes traffic from the container to the host machine dynamically. It is required for Xdebug. It dynamically resolves the host’s IP address without hardcoding it
The full docker-compose.yml
file should look something like this:
networks:
laravel-network:
services:
container-laravel:
container_name: container-laravel
restart: unless-stopped
build:
context: .
dockerfile: Dockerfile
extra_hosts:
- host.docker.internal:host-gateway # required for xdebug, dynamically resolves the host's IP address without hardcoding it
volumes:
- ./:/app
ports:
- 2002:8080
networks:
- laravel-network
depends_on:
- container-laravel-database
container-laravel-database:
container_name: container-laravel-database
restart: unless-stopped
image: mysql:8
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: database
networks:
- laravel-network
volumes:
- laravel-db-data:/var/lib/mysql
volumes:
laravel-db-data: ~
Dockerfile Setup
Install Xdebug
and copy the xdebug.ini
configuration file into the container.
Please note that the Dockerfile
exposes port 8080
.
This will be important when setting up the IntelliJ IDE server settings later on.
FROM php:8.2-fpm
# Other configuration omitted for brevity..
RUN pecl install xdebug && docker-php-ext-enable xdebug
COPY ./docker/conf-xdebug/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini
# Other configuration omitted for brevity..
EXPOSE 8080
# Other configuration omitted for brevity..
Xdebug.ini File
Add the following contents to the xdebug.ini
file:
# This setting enables Xdebug by loading its shared object, xdebug.so as a Zend extension in PHP.
# Required to activate Xdebug in your PHP environment
zend_extension=xdebug.so
# This setting specifies the operational mode for Xdebug.
# Setting it to debug enables step-debugging, which lets you place breakpoints in your code and inspect variables as the code runs.
# Other possible values include develop for development diagnostics and profile for profiling code performance.
xdebug.mode=debug
# This setting makes Xdebug start debugging automatically when a request HTTP, CLI, etc. is received.
# Its convenient for debugging APIs, web pages, and CLI scripts without manually initiating each debug session.
xdebug.start_with_request=yes
# This is the port Xdebug uses to connect to your IDEs debugger.
# Port 9003 is the default for Xdebug 3 previous versions used 9000.
# Ensure your IDE is set to listen on this port for incoming Xdebug connections.
xdebug.client_port=9003
# This setting tells Xdebug where to send debugging information.
# In Docker, host.docker.internal is an alias for the host machines IP address, allowing containers to communicate with services on the host, such as an IDE listening for Xdebug connections.
# This way, Xdebug can connect back to your IDE running on the host for debugging sessions.
# Note: If host.docker.internal doesn't work particularly on Linux, you may need to use a fixed IP xdebug.client_host=172.17.0.1 or specify it dynamically in the Docker Compose file
xdebug.client_host=host.docker.internal
# This setting forces PHP to display errors, regardless of the display_errors setting in php.ini.
# Setting it to 1 ensures that errors are always shown in the output, which is especially useful during debugging since it overrides other
# PHP configurations that might suppress errors in production environments.
xdebug.force_display_errors = 1
# This controls the verbosity of the Xdebug logs.
# The levels range from 0 no logging to 7 maximum verbosity.
# Setting it to 3 the default provides a moderate level of detail, logging essential information and errors, which helps in diagnosing common issues without overly detailed output.
xdebug.log_level=3
# Xdebug logs connection and debugging errors to this file, making it easier to troubleshoot connectivity issues or any misconfiguration.
# You can review this file to understand why a debug session might not be starting, or to verify that Xdebug is trying to connect to your IDE.
xdebug.log=/var/log/xdebug.log
Configuring IntelliJ IDE
In your IDE, navigate to File > Settings > Language & Frameworks > PHP > Servers
Add a server by clicking the + icon.
Next, populate the following:
- Provide a name in the
Name
field. - For the
Host
field, add localhost. - For the
Port
field add 8080, as this is the port the DockerFile is exposing, if you using a different port add your port instead. - For
Debugger
, select Xdebug, This should be selected by default. - Check the
Use path mappings
checkbox. - In the
Absolute path on server
, provide the path to the files in the docker container, in my case my Laravel project is being mapped to /app inside the container
Click Apply.
Next, navigate to Language & Frameworks > PHP > Debug
Ensure that port 9003 exists in the Debug Port
input field.
Uncheck the following two checkboxes:
- Force break at first line when no path mapping specified
- Force break at first line when a script is outside the project
Click Apply and then OK to close the window.
Debugging with Xdebug
Start up your project by running docker-compose up
Listen for Debug Connections
by navigating to:
Run > Start Listening for PHP Debug Connections
Add a breakpoint at a desired location of your choice and perform a request.
That's it, you should now have Xdebug working with docker.
Happy Debugging!