Setting up xdebug with Docker and PHPStorm

A quick guide to how to do this, since I always forget and have to look it up. This is done with docker4drupal, but should work equally well with any Docker Compose setup.

Enable xdebug on the relevant Docker container. For docker4drupal this means uncommenting these lines in the docker-compose.yml file:

PHP_XDEBUG: 1
PHP_XDEBUG_DEFAULT_ENABLE: 1
PHP_XDEBUG_REMOTE_CONNECT_BACK: 0
PHP_IDE_CONFIG: serverName=PHPSTORM
PHP_XDEBUG_IDEKEY: "PHPSTORM"
PHP_XDEBUG_REMOTE_HOST: 172.17.0.1 # Linux

If you enable these after you've created the PHP container, remember to restart the container so that xdebug is enabled and configured.

Now go to Settings > Languages & Frameworks > PHP and set your language level as required. Add a new CLI interpreter by clicking .... Click the + on the top left and add a new Docker configuration. Select Docker Compose and the php service, then use the default options for everything else. Save this and apply.

Next click the 'Add configuration' button on the taskbar in the top right. Pick the PHP Remote Debug template and click the + on the top left to add a new configuration (don't make the mistake of editing the template). Check 'Filter debug connection by IDE key' and set the IDE key to match the one in your XDebug config (for the above we'd use PHPSTORM). Add a server (the name doesn't matter). Give it the appropriate host and port - for docker4drupal the host will be something like http://myproject.docker.drupal.localhost, and the port will be 8000 unless you've changed it. Check 'Use path mappings', and set a path mapping for the root directory to /var/www/html (or wherever it's mounted to on the container).

It's important to note that for this to work with Drush, or anything that exists both in Composer and globally, you need to invoke Drush from the binary in the vendor directory vendor/bin/drush rather than using the system Drush, so that PHPStorm can use the path mappings. You could do this with a make command or Composer script. A make command I've used in the past:

make VENDOR_BIN ?= /var/www/html/vendor/bin

drush:
  docker exec $(shell docker ps --filter name='^/$(PROJECT_NAME)_php' --format "{{ .ID }}") $(VENDOR_BIN)/drush -r $(DRUPAL_ROOT) $(filter-out $@,$(MAKECMDGOALS))

This is a modified version of the default docker4drupal command.