Configuring Xdebug with Docker Compose and IntelliJ on Ubuntu

Jiyaad Dolly
5 min readNov 3, 2024

--

Photo by Nathan Cima on Unsplash

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 resolve host.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.iniconfiguration 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.

Setup a Server to allow Xdebug to communicate between host machine and docker container

Next, navigate to Language & Frameworks > PHP > Debug
Ensure that port 9003 exists in the Debug Port input field.

Uncheck the following two checkboxes:

  1. Force break at first line when no path mapping specified
  2. Force break at first line when a script is outside the project

Click Apply and then OK to close the window.

Configure Xdebug settings

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!

--

--

Jiyaad Dolly
Jiyaad Dolly

Written by Jiyaad Dolly

0 Followers

I’m a Magento, Laravel, and Angular Developer from South Africa. I also work with Docker and REST APIS. I'm here to share my knowledge with other developers.

No responses yet