In this article, I'm going to introduce a more convenient way to quickly set up development environment with PHPStorm, Docker, Docker compose and Xdebug. The source code for docker compose configs. The Dockerfile is based on the php:7-apache image. It installs and configure Xdebug. The most important parameters are xdebug.remotehost and xdebug.idekey, which I commented inside the Dockerfile. I included a docker-compose.yml so you can inspire yourself from it, but also get and up in running easily to make sure everything works. Finally, you just need to set two environment variables to enable debugging for PHP: XDEBUGCONFIG: accepts a list of settings, but we only need to set the clienthost to tell XDebug which machine hosts the IDE to which to connect (Docker handily provides the host.docker.internal alias for MacOS and Windows). Use docker-compose logs -follow to inspect the logs to find out what errors are occurring; Fix the problem; Rebuild and restart the containers with docker-compose up -d -build; Lather, rinse, repeat; If you need any further information, check out the official Docker Compose documentation, or post a question in a comment, and I’ll see if I. Install Xdebug 3 in the PHP container The php container uses a custom Dockerfile (./docker/php/Dockerfile) to define its build steps, which you can see in the example below. This is because Xdebug doesn’t come 'bundled' with the official Docker Hub PHP containers.

Below I describe how I use Docker Compose for my PHP projects, although most of the concepts are helpful for any technology that you use. I will use Magento as an example, but there’s near-zero Magetno-specific stuff and this will work for any framework that you use.

Docker-compose Php-fpm Xdebug

I don’t pretend to be the author of all the techniques described here, I give all the thanks and credits to people that actually invented this.

Folder structure

This is how I organize files in the repo:

The docker folder contains all docker-related files except for Docker Compose YAMLs.

I put all files for local (development) purpose into a local sub-folder. This is becasue you might want to keep different Dockerfiles and configs for diferent environments in your repository as well.

Say, you have a “Testing” environment. Then:

  • put Dockerfiles and configs to docker/testing folder.
  • create docker-compose.testing.yaml in the root folder.
  • bring your containers up on the testing environemnt by running:
    docker-compose -f docker-compose.testing.yaml up --build -d

As local environment is used most often, I prefer local YAML files not to have “.local” suffix, so that I don’t need to specify the list of files each time for docker-compose commands.

docker-compose.yaml

The contents should be self-explanatory. The only trick here is using YAML alias (codebase) not to repeat ourselves with mounting application volume to both nginx and php-fpm containers.

As you can see I also prefer to name my services in a more abstract way than just “php” or “nginx”. I like it more because I can change the underlying technology later without much pain (i.e. mariadb to mysql).

I also include the app name in the service name so that it is possible to run different, let’s say, php containers in the same network.

Using override file

Note that I don’t expose or map any ports in docker-compose.yaml above. I find this important because another developer can have ports that I use already taken on his machine. To manage this I use docker-compose.override.yaml which is loaded by default if present. Find out more about it at https://docs.docker.com/compose/extends/.

I keep this file ignorred by GIT and instead version docker-compose.override.example.yaml file, so that it is easy for everyone to start.

docker-compose.override.yaml

Here I map nginx container port 80 to local port 8080 so I can open my website in browser: http://magento.localhost:8080.

Config

I also map mariadb container port 3306 to local port 3326 so that I can connect to the database from my local machine: mysql -h 127.0.0.1 -P 3326 -u root -p magento.

User permissions trick

By default docker containers are running from the root user. Sometimes they use custom user, like “nginx” for example. So files that are created in containers might appear owned by root or even unknown user in mounted folders on your local machine.

To overcome this inconvenience I use the following trick and change the user IDs inside containers to my local user.

  1. In your Dockerfile define the USER_ID and GROUP_ID args and modify the user from which the container is running:

For example for nginx we’ll have:

For php-fpm:

  1. In your docker-compose.override.yaml define the actual user and group IDs that you want to use:

You can find out your current local user and group IDs with id -u and id -u respectively. Normally in Ubuntu these are both 1000.

Working with Composer

I only work with composer locally, never run it inside the container. This allows me not to care about copying ssh keys, composer repository credentials and other stuff.

As a disadvantage this leads to necessity of having PHP and Composer installed locally, but I always do have them latest anyway. However it is important to specify the PHP version that you use on the project for composer, so that it installs correct packages. You can do it like this in composer.json:

Xdebug Php Docker

You can also specify PHP extensions versions here, see platform section documentation for more capabilities.

With properly configured platform in composer.json you can avoid adding “–ignore-platform-reqs” to your composer install or update command.

Bin helper

All modern frameworks have CLI interface for development purposes and it is being used quite often. Normally you must do this inside the container for it to work properly, but that’s not very convenient. The elegant way to improve this is to create a “bin helper” as I call it, which will pass the command you want to the container you need.

Below is the example for Magento, you can modify it for the framework of your choice:

Docker Php Fpm Xdebug

bin/magento

So now I just run this as if it would be the actual bin/magento file:

Phpstorm Xdebug Docker Cli

That’s it for now.

Docker-compose Install Xdebug

Check out related topics: