Creating a PHP Apache Docker service with full xdebug support on WSL

A recent project required PHP and Apache, I needed to refactor all the code. Trouble is? I couldn't get xdebug working with my PHP setup in WSL. I decided to containerise the Apache and PHP side of things anyway, because I had other PHP projects to work on and I didn't want conflicting configs... But how do you setup xdebug inside Docker to be available on the host machine?

The PHP Apache Dockerfile

Before we setup our dockercompose.yml, we'll need a special Dockerfile with a few configs to setup PHP and xdebug.

First our Dockerfile in our /docker/php-xdebug directory

FROM php:8.2-apache
RUN apt-get update \
    && apt-get install -y bash \
    && docker-php-ext-install mysqli pdo_mysql \
RUN pecl install xdebug \
    && docker-php-ext-enable xdebug
EXPOSE 80

We install all the packages we need, and we enable the xdebug extension.

Now we need our xdebug.ini file:

zend_extension=xdebug

[xdebug]
xdebug.mode=develop,debug
xdebug.start_with_request=yes
xdebug.client_host=host.docker.internal
xdebug.client_port=9003
xdebug.log_level=0
xdebug.idekey=VSCODE

This will configure xdebug to use the host.docker.internal host, allowing it access to the host machine (and vice versa).

Our PHP Apache xdebug service is ready!

Docker Compose

Now we're ready to bring all our services together:

services:
  php-apache-xdebug:
    build:
      context: ./docker/php-apache-xdebug
      dockerfile: Dockerfile
    container_name: php-apache-xdebug
    command: ["sh", "-c", "apache2-foreground"] 
    volumes:
      - ./html:/var/www/html
      - ./docker/php-apache-xdebug/xdebug.ini:/usr/local/etc/php/conf.d/xdebug.ini
    environment:
      XDEBUG_MODE: debug
      XDEBUG_CONFIG: "client_host=host.docker.internal client_port=9003 start_with_request=yes"
    extra_hosts:
      - "host.docker.internal:host-gateway"
    ports:
      - "80:80"
    depends_on:
      - mysql
    networks:
      - frontend
      - backend
  mysql:
    image: mysql:8.0
    container_name: mysql
    volumes:
      - "./db/db.sql:/docker-entrypoint-initdb.d/db.sql"
      - "./db/:/mysql/db"
    environment:
      MYSQL_USER: admin
      MYSQL_PASSWORD: ${DBPASSWORD}
      MYSQL_ROOT_PASSWORD: ${DBPASSWORD}
      MYSQL_DATABASE: my_db
    ports:
      - "3306:3306"
    networks:
      - backend
networks:
  backend:
    driver: bridge
  frontend:
    driver: bridge

The environment variables in php-apache-debug are vital, as they assign teh correct host and client ports for xdebug. But with that? You should be able to stick whatever PHP you like and debug it with VSCode's xdebug extensions, no issues!