Xdebug with SSH tunnel on Docker for Mac Xdebug with SSH tunnel on Docker for Mac docker docker

Xdebug with SSH tunnel on Docker for Mac


Here is what did work for me.

Inside Docker Container

Edit xdebug configuration

# automatically start debugger on every requestxdebug.remote_enable=1xdebug.remote_autostart=1xdebug.remote_port=9000# send all debug requests to 127.0.0.1, remote_connect_back should be turned offxdebug.remote_connect_back = 0xdebug.remote_host=127.0.0.1#log all xdebug requests to see is it working correctlyxdebug.remote_log=/var/log/remote.log

Verify that xdebug works

At this point try to run PHP application. Log should contain such entries for every request:

I: Connecting to configured address/port: 127.0.0.1:9000I: Connected to client. :-)

If you see something like this in the log, remote_host or remote_connect_back are configured incorrectly.

I: Checking remote connect back address.I: Checking header 'HTTP_X_FORWARDED_FOR'.I: Checking header 'REMOTE_ADDR'.I: Remote address found, connecting to 172.18.0.1:9000.W: Creating socket for '172.18.0.1:9000', poll: Operation now in progress.E: Could not connect to client. :-(

I've seen situations when Xdebug worked in CLI but not from the browser, when this issue appeared in the log, remote_connect_back=0 fixed it.

sshd configuration

In order to allow ssh tunnelling to the container: edit /etc/ssh/sshd_conf and add:

GatewayPorts yes

Restart sshd if needed (ideally this should be part of the Dockerfile).

On Host Machine

Start reverse SSH tunnel

Run this command and keep it in separate Terminal tab open:ssh -p {container_22_port} -R 9000:localhost:1111 root@127.0.0.1

where {container_22_port} is the port on host machine mapped to the exdposed 22 port on docker container. 9000 is the port used by Xdebug inside container, 1111 port that will be used by host machine to listen to Xdebug connections.

Test with netcat

At this point you can verify that Xdebug actually passes information from inside docker container to the host machine. Start netcat to see what is sent to the 1111 port and run php application:

nc -l 1111

You should see something like this:

<?xml version="1.0" encoding="iso-8859-1"?><init xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" fileuri="file:///var/www/magento2/index.php" language="PHP" xdebug:language_version="7.0.12" protocol_version="1.0" appid="1006" idekey="XDEBUG_ECLIPSE"><engine version="2.5.0rc1"><![CDATA[Xdebug]]></engine><author><![CDATA[Derick Rethans]]></author><url><![CDATA[http://xdebug.org]]></url><copyright><![CDATA[Copyright (c) 2002-2016 by Derick Rethans]]></copyright></init>

Configure PhpStorm

Opne File->DefaultSettings, and there in Languages&Frameworks->PHP->Debug change Xdebug->Debug port to 1111 (the one we used to open ssh tunnel).PhpStorm should start accepting connections from xdebug at this point.

Are there any concerns with this approach?


I found out that you don't need a SSH tunnel to get it to work.

Xdebug need only to connect out to the running IDE debugger but there might be some default ports already used like the one for FPM (9000).

Inside the container

Set the xdebug options as this:

xdebug.remote_enable = 1xdebug.remote_host = localhostxdebug.remote_port = 10000xdebug.remote_connect_back = 1

Note: if using the nginx-proxy container as reverse proxy set your remote_host as the one you defined in the VIRTUAL_HOST

Using PhpStorm

  • File -> Settings
    • Languages & Frameworks
      • PHP
        • Servers: add one and set the host as localhost: 80 with Xdebug with Path mapping selected ... map the folder INSIDE the Docker (/var/www/) to the one
        • Debug: set the Xdebug port to 10000 with the Can accept external connections checked


use xdebug.remote_host=host.docker.internal works everywhere.