Solved: Remote XDebug from Dockerized PHP app via SSH Tunnel on Ubuntu
expose:
- "9000"
- Remove the
ports:
section fromdocker-compose.yml
and define expose - On the remote machine enable
GatewayPorts clientspecified
in/etc/ssh/sshd_config
(then restart the sshd service). - This allows you to create an SSH port forward tunnel which listens on all network interfaces (
0.0.0.0
or*
) which is required in order for the Docker container's virtual network interface to reach your client machine via the tunnel. By default, theGatewayPorts
setting limits remote port forwardings to bind to thelocalhost
interface only which Docker can't "see".
Change SSH connection string to explicitly specify that I wanted to listen on the global interface *
:
ssh -R *:9000:localhost:9000 username@example.com
Or with Putty/Kitty
After doing all this, I was finally able to connect to Xdebug running inside a Docker container on the remote server from my local machine. 🎉
.vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch built-in server and debug",
"type": "php",
"request": "launch",
"runtimeArgs": [
"-S",
"localhost:8000",
"-t",
"."
],
"port": 9000,
"serverReadyAction": {
"action": "openExternally"
}
},
{
"name": "Debug current script in console",
"type": "php",
"request": "launch",
"program": "${file}",
"cwd": "${fileDirname}",
"externalConsole": false,
"port": 9000
},
{
"name": "Listen for Xdebug 9000",
"type": "php",
"request": "launch",
"port": 9000,
"pathMappings": {
"/var/www/html/": "${workspaceRoot}/",
},
}
]
}
xdebug-php.ini
zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20230831/xdebug.so
xdebug.mode=debug
xdebug.client_port=9000
;xdebug.client_host=dockerhost
xdebug.client_host=xdebug://gateway
xdebug.idekey=PHPSTORM
xdebug.start_with_request = yes
Optionally, if you want to explicitly force Xdebug to connect only to the host machine (meaning you only want to use Xdebug via the SSH tunnel), either:
Add the following section to your service in docker-compose.yml
:
extra_hosts:
- host.docker.internal:host-gateway
Then set xdebug.client_host=host.docker.internal
and xdebug.discover_client_host=Off
or
- Set
xdebug.client_host=xdebug://gateway
P.S. A useful command while debugging this was nc -vz 127.0.0.1 9000
which allowed me to check if my SSH port forward was working on the host machine, at least.
Original credits to WackGet