Table of Content


After the several bunch setup of Docker+xDebug+PHPStorm I understood that there are some moments which should be noted. I’m going to explain in details how to setup Docker that it’ll works correctly on Linux, macOS and Windows.

Docker Setup

Dockerfile is prety simple, we use php:7.2-fpm image and add xDebug configuration:

FROM php:7.2-fpm

# Set server timezone
RUN rm /etc/localtime
RUN ln -s /usr/share/zoneinfo/Europe/Kiev /etc/localtime

# Set PHP timezone
RUN printf '[PHP]\ndate.timezone = "Europe/Kiev"\n' > /usr/local/etc/php/conf.d/tzone.ini

# Install and Setup xDebug
RUN apt-get update \
# Add "ip" tools for resolve "host.docker.internal" through entrypoint automatically, because there is no suport "for-linux" at this time (@see
    && apt-get -y install iproute2 \
    && apt-get -y install iputils-ping \
    && pecl install xdebug-2.6.0 \
    && docker-php-ext-enable xdebug \
    && touch /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \
    && echo "error_reporting=E_ALL" > /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \
    && echo "display_startup_errors=1" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \
    && echo "display_errors=1" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \
    # Full path to -> =/usr/local/lib/php/extensions/no-debug-non-zts-20151012/
    && echo "" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \
    && echo "xdebug.remote_enable=1" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \
    && echo "xdebug.remote_autostart=0" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \
    && echo "xdebug.remote_connect_back=0" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \
    && echo "xdebug.remote_handler=dbgp" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \
    && echo "xdebug.idekey=PHPSTORM" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \
    && echo "xdebug.remote_host=host.docker.internal" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \
    && echo "xdebug.remote_port=9000" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \
    && echo "xdebug.profiler_enable=0" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \
    && echo "xdebug.profiler_output_dir=\"/var/www/xdebug\"" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini

# Install composer
RUN curl -sS | php -- --install-dir=/usr/local/bin --filename=composer

Docker-compose setup

docker-compose.yml has some interesting options which I describe in detail below.

version: '3'

      context: .
      dockerfile: .docker/php/Dockerfile
      PHP_IDE_CONFIG: "serverName=app" # PHPStorm Server name
      XDEBUG_CONFIG: "remote_host=host.docker.internal"
    working_dir: /var/www/html
    entrypoint: ["./.docker/php/"]
      - .:/var/www/html

Network setup

There is network_mode: "host" feature which can resolve problem with unified host but it works only on Linux, so this approach is rejected.

The next two configurations are only actual if you are on Linux machine otherwise you can skip this step.

Variant A

Docker on Windows and macOS setup host.docker.internal host under the hood and this allow connect from Docker container to Docker host with unified name, but this feature in not available on Linux yet.

The issue with this problem is registered on GitHub and even there is PR which add support for host.docker.internal on Linux. When this PR will be accepted we can use host.docker.internal without any hacks on Linux.

We specialy add entrypoint to docker-compose config, this script allow us resolve host.docker.internal if we on Linux machine. So, add next script to .docker/php/ script:

#!/usr/bin/env bash

ping -q -c1 HOST_DOMAIN > /dev/null 2>&1;
if [[ $? -ne 0 ]]; then
    HOST_IP=$(ip route | awk 'NR==1 {print $3}');
    echo -e "$HOST_IP\t$HOST_DOMAIN" | tee -a /etc/hosts;

cd /var/www/html

php-fpm -F

This script check if host.docker.internal can be resolved and on the failure add record to /etc/hosts file.

Variant B

You can add qoomon/docker-host image to your docker-compose.yml then change xdebug.remote_host to xdebug.remote_host=dockerhost in all places and it will works.

version: '3'

      context: .
      dockerfile: .docker/php/Dockerfile
      PHP_IDE_CONFIG: "serverName=app" # PHPStorm Server name
      XDEBUG_CONFIG: "remote_host=host.docker.internal"
    working_dir: /var/www/html
    entrypoint: ["./.docker/php/"]
      - .:/var/www/html
    depends_on: [ dockerhost ]
    image: qoomon/docker-host
    cap_add: [ 'NET_ADMIN', 'NET_RAW' ]
    restart: on-failure

depends_on: [ dockerhost ] is required it this case.

PHPStorm configuration

  1. Go to the Settings (Ctrl+Alt+S) Languages & Frameworks > PHP > Debug > xDebug (screenshot)

    • Debug port – 9000

      Debug port must be equal to xdebug.remote_port=9000 in .docker/php/Dockerfile file

  2. Go to the Settings (Ctrl+Alt+S) Languages & Frameworks > PHP > Servers

  3. Press green "+" button, enter next parameters (screenshot), all options are important:

    • Name – app

      Name must be equal to PHP_IDE_CONFIG: "serverName=app" environment variable in docker-compose.yml, but you can use any name, app is only as example.

    • Host – localhost
    • Port – 8080
    • Debugger – Xdebug
    • Check Use path mappings…: <path/to/project/root-dir> -> /var/www/html.

      Hint: To submit the "absolute path on the server" press Enter after typing the path in the text field. If you only click out of the field, your input will be removed.

  4. Press "Apply" and "OK";

  5. Reload Docker with:

    $ ./bin/docker-compose down
    $ ./bin/docker-compose up
  6. Set breakpoint in your code

  7. Press Start listening for PHP Debug Connection in PHPStorm

  8. Open project in Web browser on http://localhost:8080.

Useful links

Last modified: 12.07.2019



Write a Reply or Comment

Your email address will not be published.