Apr 21, 2017

Using xDebug and Sublime Text with Docker

I've used xDebug with Sublime Text locally for quite some time but have started playing with Docker containers to instantiate instances of Apache, PHP, MySQL, and Drupal 8.

The Docker image I use has xDebug enabled for PHP, but I wanted to have xDebug running in the container to communicate with Sublime running on my local host system. This is not complicated, but it still took quite awhile for me to determine the correct settings.

Some of my confusion was due to the terms server and client as used in documentation and comments. Most of the time, server refers to xDebug running within PHP, and client refers to the IDE or text editor such as Sublime.

On the other hand, apparently it is xDebug that initiates the connection to the IDE, which makes xDebug act like a client. Also, xDebug has a setting called remote_host which sounds like a remote server that it is communicating with.

In the container I'm running, the xDebug settings are in

  /etc/php5/mods-available/xdebug.ini

Here are tips to get these components working together.

Run ifconfig in a local terminal to get the local ip address.

Working on my laptop connected to a home router, ifconfig shows eth0 with inet addr 10.0.0.3. I use that value as follows in xdebug.ini 

  xdebug.remote_host = 10.0.0.3

At a public library using their wi-fi, ifconfig shows wlan0 with inet addr 10.12.13.211, for example, but the address changes from session to session.

  xdebug.remote_host = 10.12.13.211

This is the key difference from running in a purely local way without Docker, where localhost is a typically used value for the remote_host setting.

Here are the settings that need to be present in xdebug.ini.

  xdebug.remote_enable = On
  xdebug.remote_host = 10.0.0.3
  xdebug.remote_port = 9000


If you have trouble getting your setup to work, use a log for xDebug to record errors and warnings. Enable the log by adding the following directive into your xdebug.ini file, e.g.

  xdebug.remote_log = /tmp/xdebug.log

This is useful for debugging. For example, at the beginning of the log there will probably be an indication of whether xDebug is even able to connect to the client, which is an important clue.

But use this key only as needed since it can generate a lot of log messages, some of which seem spurious.

For the Sublime editor, the key setting is path_mapping. Its value is an object that indicates corresponding paths. For example,

  { "/var/www/modules/custom/optimizely/": "/var/www/html/opti/modules/contrib/optimizely/" }

The key (the left side) is a path in the Docker container where the xDebug server finds its source code. Its value (the right side) is the path in the local system where Sublime finds the corresponding code.

In my use case, I am only interested in the code for the Optimizely module, so I'm only providing a mapping between the two root directories of the module.

Here are the settings that need to be present in Sublime for its xDebug package.

    "port": 9000,
    "path_mapping": { "/var/www/modules/custom/optimizely/": "/var/www/html/opti/modules/contrib/optimizely/" },

If you need to do troubleshooting, you might add the following setting as well in order for Sublime to output messages to its own local xDebug log.

    "debug": true

Also use this key only as needed since it can generate a lot of log messages, some of which seem spurious.

No port forwarding is needed.

The Docker documentation states: "By default Docker containers can make connections to the outside world ..." Since it is xDebug within the container that initiates the connection to Sublime running outside, there is no need to use port forwarding for the port between them.

Once you've got the correct settings for xdebug.ini, there are different ways to persist them. In my case, some settings don't change, but I work in different locations where the IP address for remote_host does vary, so I took a hybrid approach.

First, I used the docker commit command to capture the current state of a container into an image. In that container I had edited xdebug.ini with the settings that remain the same.

# docker commit distracted_dijkstra drupal-xdebug

Second, I use the docker run command with the -e option to provide the IP address as an environment variable when instantiating the image in a new container.

# docker run -e XDEBUG_CONFIG="remote_host=10.0.0.3" drupal-xdebug


Sources:

Xdebug 2 | Remote Debugging
https://xdebug.org/docs/remote#browser_session

martomo / SublimeTextXdebug
https://github.com/martomo/SublimeTextXdebug/blob/master/Xdebug.sublime-settings

Debug your PHP in Docker with Intellij/PHPStorm and Xdebug
https://gist.github.com/chadrien/c90927ec2d160ffea9c4

No comments:

Post a Comment