Search code examples
phpdockerxdebugssh-tunneldocker-for-mac

Xdebug with SSH tunnel on Docker for Mac


I was reading a lot of posts from the Docker community recently on how to debug PHP application in the PHPStorm with the Docker for Mac. All of them contains pieces of useful information, but haven’t seen working solution in one place.


Solution

  • Here is what did work for me.

    Inside Docker Container

    Edit xdebug configuration

    # automatically start debugger on every request
    xdebug.remote_enable=1
    xdebug.remote_autostart=1
    xdebug.remote_port=9000
    # send all debug requests to 127.0.0.1, remote_connect_back should be turned off
    xdebug.remote_connect_back = 0
    xdebug.remote_host=127.0.0.1
    
    #log all xdebug requests to see is it working correctly
    xdebug.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:9000 I: 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?