Setting up PhpStorm to Work with Docker Compose, Xdebug and PHPUnit for Local Development
Kofi Oghenerukevwe H.
Posted on December 7, 2019
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
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).
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..."
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.
Run your 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.
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
Select the docker-compose service that contains your PHP installation. For me, that's the web service.
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.
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.
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
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
December 7, 2019