Setting up Xdebug for Docker Development in PhpStorm

Leo Sjöberg • January 22, 2018

+++ Big thanks to Luke Waite who did most of the heavy lifting to figure this out over at Intouch.

Do you still throw in dd(), or var_dump() and die() in your code to debug? And then redo your request with another call like that elsewhere in the code to follow the data through your codebase? Ever found this terribly inefficient and thought "I'll just setup Xdebug", and then realised making it work with Docker isn't quite as easy as you thought? Yeah, me too.

Nginx Configuration

"Server? But I'm just debugging PHP!". Well, for PhpStorm to correctly initialise debug connection, our server needs to respond with the correct SERVER_NAME. So if your configuration doesn't already have it, you just need to add a server_name. The easy way to do it is adding the following line:

1fastcgi_param SERVER_NAME $host;

This will set the SERVER_NAME to the requested host (localhost in our case), which helps PhpStorm figure out which configuration to use for mapping your local directories to the ones on the "server" (docker container).

PHP Configuration

In order to enable Xdebug, you need to do two things:

  1. Install Xdebug
  2. Configure Xdebug

To do all this in one, add this to your PHP container's Dockerfile:

1RUN pecl install xdebug-2.5.5 && \
2 docker-php-ext-enable xdebug && \
3 echo "xdebug.remote_enable=on\nxdebug.remote_autostart=off\nxdebug.remote_host=169.254.10.100\nxdebug.remote_port=9001" > /usr/local/etc/php/conf.d/xdebug.ini

The first two rows will install and enable Xdebug, and the last line will write a configuration file, xdebug.ini which will be read by PHP. That file ends up looking like this:

1xdebug.remote_enable=on
2xdebug.remote_autostart=off
3xdebug.remote_host=169.254.10.100
4xdebug.remote_port=9001

Here, we are hardcoding a remote_host. From what I could tell, pretty much the entire internet tells you to put your local IP address there. However, that doesn't work very well in a team where everyone has a different one. As such, we will configure a loopback interface for 169.254.10.100 on our local machine, so that Xdebug can connect.

Note that we're setting the remote_port here to 9001. This is completely optional, and debug will default to port 9000. However, if you're running something locally on port 9000 (like a local instance of PHP, if you run Laravel Valet or similar as well), the port will already be in use, meaning PhpStorm cannot use the port to listen for Xdebug connections. For this reason, we use 9001, but you can set this to whatever you want.

Setting up a loopback interface (alias)

So what is this magical "loopback interface" that lets us use a static IP address in the configuration? Without going into too much detail, for our purposes, it's a way to make our localhost available to the docker container on a specific IP address. If we're being technical, this is not a true loopback interface, but rather an alias (I only write this to not upset all the sysadmins in the world), but that's irrelevant for now.

To setup the loopback interface, run

1sudo ifconfig lo0 alias 169.254.10.100

Now, Xdebug can hit 169.254.10.100 to connect to our IDE.

Configuring PhpStorm to accept connections

The final piece to the puzzle is configuring PhpStorm to correctly map to your local project, so that you can actually debug your application. This is reasonably straightforward, just follow the steps:

  1. Open the settings panel
  2. Languages & Frameworks > PHP > Debug > DBGp Proxy
  3. Set IDE key: PHPSTORM
  4. Set Host: 127.0.0.1
  5. Go to Languages & Frameworks > PHP > Debug
  6. Under Xdebug, change the debug port to 9001
  7. Go to Languages & Frameworks > PHP > Servers, add a new server named localhost, and add a path mapping /var/www/html to your project folder, with host localhost and port 80

This is the basic configuration required. To start listening for connections, simply go to Run > Start listening for PHP debug connections

Wrapping up

You've now completed the entire setup required to run Xdebug through Docker on your local machine! All that's left to do is adding a bunch of breakpoints, and start enjoying your new experience, filled with stack traces and complete request data.