Setting up PhpStorm to Work with Docker Compose, Xdebug and PHPUnit for Local Development

rukykf

Kofi Oghenerukevwe H.

Posted on December 7, 2019

Setting up PhpStorm to Work with Docker Compose, Xdebug and PHPUnit for Local Development

Contents

Introduction

I decided to write this article because I was frustrated by how difficult it was to find all the information I needed to make these technologies work well together in a single article. I am hoping this resource can be a good reference for myself and for others who might run into the same issues that I ran into.

In this article we'll go through the following:

  • Setting up the PhpStorm IDE so we can start and stop our docker-compose containers from within the IDE
  • Debugging our code with PhpStorm and Xdebug (with Xdebug installed in a docker-compose service container)
  • Running our test-suite with PhpStorm and PHPUnit (with PHP installed in a docker-compose service container)

Note: The information in this article should work well with PhpStorm version 2019.2 and up. Please be aware that some of the configuration options I am about to discuss are not available in certain older versions of PhpStorm.

Part 1: Configurations for docker-compose.yml, Dockerfile and Xdebug

The docker-compose.yml and Dockerfile configuration files I'm using for this article were created by Peter Fisher of How to Code Well and slightly modified by me. You can get access to the original files from his Freecodecamp PHP OOP course Github repository.

In the docker-compose file I'm using for this tutorial I have 3 services (2 database services and one web service) as you can see in this snippet:

docker-compose.yml



version: '3'

volumes:
  mysql_data:
  mysql_data_test:

networks:
  dev_network:

services:
  web:
    build:
      context: .
    ports:
      - 8080:80
    volumes:
      - .:/var/www/html
      - ./dockerconfigs/000-default.conf:/etc/apache2/sites-enabled/000-default.conf
      - ./dockerconfigs/php.ini:/usr/local/etc/php/php.ini
    environment:
      APACHE_DOCUMENT_ROOT: /var/www/html/public
      XDEBUG_CONFIG: remote_host=host.docker.internal
    networks:
      - dev_network
    restart: on-failure

  db:
    image: mysql:5.7
    volumes:
      - mysql_data:/var/lib/mysql
    environment:
      - MYSQL_DATABASE=devDB
      - MYSQL_ROOT_PASSWORD=test
    networks:
      - dev_network
    restart: on-failure


  db_test:
    image: mysql:5.7
    volumes:
      - mysql_data_test:/var/lib/mysql
    environment:
      - MYSQL_DATABASE=devTestDB
      - MYSQL_ROOT_PASSWORD=test
    networks:
      - dev_network
    restart: on-failure


Enter fullscreen mode Exit fullscreen mode

The web service from the docker-compose file above references this Dockerfile in its build context



FROM php:7.3-apache

LABEL maintainer="Peter Fisher"

RUN apt-get update          \
    && apt-get install -y   \
        git                 \
        zlib1g-dev          \
        zip                 \
        unzip               \
        libxml2-dev         \
        libgd-dev           \
        libpng-dev          \
        libfreetype6-dev    \
        libjpeg62-turbo-dev \
        libzip-dev          \
    && pecl install xdebug                                                             \
    && docker-php-ext-install mysqli pdo_mysql iconv simplexml                                      \
    && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/  \
    && docker-php-ext-configure zip --with-libzip                                                   \
    && docker-php-ext-install gd zip                                                                \
    && docker-php-ext-enable xdebug                                                          \
    && apt-get clean all                                                                            \
    && rm -rvf /var/lib/apt/lists/*                                                                 \
    && a2enmod rewrite headers

RUN curl -sS https://getcomposer.org/installer | php -- --filename=composer --install-dir=/bin

ENV PATH /root/.composer/vendor/bin:$PATH
EXPOSE 9000

WORKDIR /var/www/html


Enter fullscreen mode Exit fullscreen mode

Note: Xdebug, PHP, PHP-CLI and Apache are installed in the Dockerfile for the web service. Also notice that Xdebug's port 9000 is exposed.

Configuring Xdebug

In the web service for the docker-compose file I am binding a php.ini file from my host machine into the web service container.



services:
  web:
    build:
      context: .
    ports:
      - 8080:80
    volumes:
      - .:/var/www/html
      - ./dockerconfigs/000-default.conf:/etc/apache2/sites-enabled/000-default.conf
      - ./dockerconfigs/php.ini:/usr/local/etc/php/php.ini


Enter fullscreen mode Exit fullscreen mode

The php.ini file I am binding to the container has some configuration options for Xdebug added at the end like so:



[XDebug]
xdebug.remote_port=9000
xdebug.remote_enable=1
xdebug.remote_connect_back=1
xdebug.remote_autostart=1


Enter fullscreen mode Exit fullscreen mode

There are other ways to configure xdebug besides modifying your php.ini file. Specifically you could use an xdebug configuration file or you could add the configurations for xdebug as an environment variable right in your docker-compose. In the docker-compose file I'm using for this article, I set the xdebug configuration for remote_host under the web service container like so



 environment:
      APACHE_DOCUMENT_ROOT: /var/www/html/public
      XDEBUG_CONFIG: remote_host=host.docker.internal


Enter fullscreen mode Exit fullscreen mode

So putting everything together my PHP project in PhpStorm currently looks like this (it's a new Laravel project I scaffolded for this tutorial).

Gif showing an overview of the project

Part 2: Configuring PhpStorm

Follow these steps to create a new PhpStorm Run/Debug configuration.

Right click on your docker-compose.yml file and select "Create docker-compose.yml..."
Gif showing the right clicking of docker-compose.yml file

If you don't see this create option, wait a bit and right click again. I observed that it takes a while to show up.

A configuration box will pop up where you can modify some options. I usually change the name of my configuration to something more memorable and I like to check the force builds option. But you can leave the defaults.
Gif showing the configuration setting for PhpStorm server

Run your new run/debug configuration
Gif showing the running of PhpStorm's new run/debug configuration

Configure PHPStorm's local server to point to your docker service by going to File > Settings > Languages & Frameworks > PHP > Servers. Add a new server and set the host to localhost and the port to whatever port you are publishing your docker-compose web service to.

In my case I am publishing my web service's port 80 to my host container's port 8080 so I'd be filling in 8080 for port.

Select the Use path mappings option since we are working with docker containers and map your project root on your host to your project root in the docker container.
Gif showing the configuration setting for PhpStorm localserver

Follow these steps to configure PhpStorm's PHP CLI interpreter

Go to File > Settings > Languages & Frameworks > PHP to configure PHP's CLI. Click the Add a new CLI interpreter from Docker, vagrant... option. Then select docker-compose
Gif showing the configuration setting for PhpStorm CLI

Select the docker-compose service that contains your PHP installation. For me, that's the web service.
Gif showing the configuration setting for PhpStorm CLI

Gif showing the configuration setting for PhpStorm CLI

Ensure to select the Connect to existing container option. This is important if you're working with a separate container for your database and it ensures that PhpStorm has access to the network your containers are joined to. If you select the Always start a new container option, then each time your run PHPUnit within PhpStorm, a new container that is not joined to any of your networks will be created.

Follow these steps to configure PHPUnit in PHPStorm

Go to File > Settings > Languages & Frameworks > PHP > Test Frameworks and add a new PHPUnit by Remote Interpreter configuration. In the dialog that comes up, select the CLI interpreter we created in the previous step from the drop-down.

Gif showing the configuration setting for PhpStorm's PHPUnit

Now you should be able to run your PHPUnit tests within PhpStorm without doing a docker exec into your service container.

Follow these steps to get PHPStorm to listen for XDebug on the right port

Go to File > Settings > Languages & Frameworks > PHP > Debug and ensure PhpStorm is listening for Xdebug on port 9000 and can accept external connections. Then ensure that PhpStorm is listening for debug connections.
Gif showing the configuration setting for PhpStorm's xdebug

Gif showing confirmation that Xdebug is listening for debug connections

Troubleshooting

  • If you find that you're not able to receive Xdebug connections then ensure your path mappings are in order see this step
  • If you are using multiple containers in a network, ensure that your PHP CLI interpreter has the Connect to existing container option set
💖 💪 🙅 🚩
rukykf
Kofi Oghenerukevwe H.

Posted on December 7, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related