How to reverse SSH tunnel to remote docker container for Xdebug?


There are many posts on SO and elsewhere on how to set this up. So far I’ve been unsuccessful in getting it working.

Local machine – Windows 10, with Cygwin, git bash, and WSL2 with Ubuntu installed; and MacBook Air (Mojave)
Host machine – AWS EC2 instance running Amazon Linux 2
Docker container – CentOS 7.8 running PHP with Xdebug
Remotely debug PHP code in container from local machine by utilizing a reverse tunnel from the local machine to the container.

I have gotten this working before when the PHP code was installed locally on the host machine, so the question is not around Xdebug. As soon as I moved the PHP code into the container, debugging no longer works.

What I’ve tried
Setting up a reverse tunnel from the local machine to the host EC2 instance works. For this I’m doing ssh -vvv -i "aws.pem" -R 9000:localhost:9000 user@ec2instance in terminal, cygwin, or git bash and testing with nc -z localhost 9000 || echo 'no tunnel open' on the host machine.

When I docker exec -it container bash into the container and run nc, the tunnel is not available.

I’m using docker-compose:

I have tried with and without mapping the 9000 port. I have tried variations of the ssh tunnel:

ssh -vvv -i "aws.pem" -R :9000:localhost:9000 user@ec2instance
ssh -vvv -i "aws.pem" -R user@ec2instance
ssh -vvv -i "aws.pem" -R \*:9000:localhost:9000 user@ec2instance
ssh -vvv -i "aws.pem" -R 9000: user@ec2instance (container IP)

I’ve also tried using ssh -L with no luck.

Several posts, like this one suggest adding GatewayPorts yes on the host machine. I’ve tried this as well with no change.

I have not tried using --network=host, primarily due to security concerns. I also would rather not use ngrok, as I’d like to be able to use localhost or host.docker.internal for the xdebug.remote_host setting.

For completeness, here is what I have for Xdebug:


I got this working. After reading up on the ssh man page and looking over things again, I realized I was binding to the docker container IP not the bridge (docker0) IP.

I updated my connect command to ssh -vvv -i "aws.pem" -R 9000: user@ec2instance with the right IP and the tunnel started working. I do still have GatewayPorts enabled (per the man page) and removed the 9000:9000 mapping.

I then updated my xdebug.remote_host value to the same IP and debugging is now working. Not sure why host.docker.internal didn’t work, but that’s for another day.

Leave a Reply