Setting up PhpStorm to Work Seamlessly with Docker-compose, Xdebug and PHPUnit for Local Development
Tags: docker, php, xdebug, phpunit
Published: 2019-12-07 14:28:46

---
title: Setting up PhpStorm to Work Seamlessly with Docker-compose, Xdebug and PHPUnit for Local Development
published: true
description: 
tags: docker, php, xdebug, phpunit
series: Docker Hacks
---
## Contents
 - [Introduction](#introduction)
 - [Docker-compose, Dockerfile and XDebug](#docker-xdebug)
 - [Configuring PHPStorm](#phpstorm)
	 - [Setup PHPStorm Run/Debug Configuration](#phpstorm-run-debug)
	 - [Setup PHPStorm PHP CLI](#phpstorm-cli)
	 - [Setup PHPStorm to run PHPUnit tests within docker container](#phpstorm-phpunit)
         - [Setup PHPStorm to listen for XDebug](#phpstorm-xdebug)
 - [Troubleshooting](#troubleshooting)

<a name="introduction"></a>
## 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. 

<a name="docker-xdebug"></a>
## 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](https://www.youtube.com/channel/UCjFs9wBGz4HlEJGUB6jzUmw) and slightly modified by me. You can get access to the original files from his [Freecodecamp PHP OOP course Github repository](https://github.com/pfwd/freecodecamp-PHP-OOP). 

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
```
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
```

> **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
```

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
```

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
```

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](https://thepracticaldev.s3.amazonaws.com/i/8caozn5bypftvy95y0xk.gif)

<a name="phpstorm"></a>
##Part 2: Configuring PhpStorm

<a name="phpstorm-run-debug"></a>
###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](https://media.giphy.com/media/dwRWHvzpsANvOhxIgC/giphy.gif)

>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](https://media.giphy.com/media/J5kBBNynKdMSDUx0ZK/giphy.gif)

Run your new run/debug configuration
![Gif showing the running of PhpStorm's new run/debug configuration](https://media.giphy.com/media/Pk9RwTYaSU6QkIn2lV/giphy.gif)

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. 

<a name="path-mappings"></a>

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](https://media.giphy.com/media/Q8UgtoB8CxhzQUcJ5B/giphy.gif)

<a name="phpstorm-cli"></a>
###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](https://media.giphy.com/media/QutcLJ8T8rTqsmcmqh/giphy.gif)

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](https://media.giphy.com/media/LMndqUiQAGEsLXbjTS/giphy.gif)

![Gif showing the configuration setting for PhpStorm CLI](https://media.giphy.com/media/eHdAtjajk5KnLkjQCa/giphy.gif)

> 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. 

<a name="phpstorm-phpunit"></a>
###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](https://media.giphy.com/media/YpeyE7QwxQLTPs7EQK/giphy.gif)

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

<a name="phpstorm-xdebug"></a>
###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](https://media.giphy.com/media/UQIqO9ZYEnR7I3MJAt/giphy.gif)

![Gif showing confirmation that Xdebug is listening for debug connections](https://media.giphy.com/media/Tg68JT7lN5qg8Lr5lF/giphy.gif)

<a name="troubleshooting"></a>
## Troubleshooting
- If you find that you're not able to receive Xdebug connections then ensure your path mappings are in order [see this step](#path-mappings) 
- If you are using multiple containers in a network, ensure that your PHP CLI interpreter has the **Connect to existing container** option set