V
V
Vitaly Voskobovich2017-01-29 15:43:26
PHP
Vitaly Voskobovich, 2017-01-29 15:43:26

How to connect to Xdebug running in a Docker container on a remote machine?

Colleagues, I ask for help in debugging the connection from my local machine to a remote xdebug server.
I have a development server (hereinafter referred to as host.dev) on which PHP-FPM with xdebug is running in a Docker container on Linux Alpine OS. Since the standard xdebug port 9000 is reserved for PHP-FPM, port 9001 has been allocated for xdebug .
Versions


PHP 7.1.0 (cli) (built: Dec 27 2016 19:41:35) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.1.0-dev, Copyright (c) 1998-2016 Zend Technologies
with Zend OPcache v7.1.0, Copyright (c) 1999-2016, by Zend Technologies
with Xdebug v2.5.1-dev, Copyright (c) 2002-2016, by Derick Rethans

The contents of the /usr/local/etc/php/conf.d/ xdebug.ini file inside the container are as follows:
; NOTE: The actual debug.so extention is NOT SET HERE but rather (/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini)

xdebug.remote_autostart=1
xdebug.remote_enable=1
xdebug.remote_connect_back=0
;xdebug.cli_color=0
xdebug.profiler_enable=0
xdebug.remote_handler=dbgp
xdebug.remote_mode=req

xdebug.remote_port=9001
xdebug.remote_host=localhost
xdebug.idekey=PHPSTORM

xdebug.remote_log="/tmp/xdebug.log"

Accordingly, port 9001 is forwarded from the container to the host machine.
Here is part of container php configuration in docker-compose.yml
php:
    build:
      context: ./docker/containers/php
      dockerfile: Dockerfile-dev
    volumes:
      - ./:/var/www/html
      - ./docker/containers/php/config/xdebug.ini:/usr/local/etc/php/conf.d/xdebug.ini
    ports:
      - "9001:9001"

The output of the docker ps command for the php container confirms the port forwarding.
In the PORTS column opposite the php container - 9000/tcp, 0.0.0.0:9001->9001/tcp
At this stage, I should be able to connect to xdebug from host.dev and work.
Now, I need to connect to Xdebug on host.dev from my local machine.
But, the whole problem is that my local machine is behind a router on which port forwarding does not work. Instead of solving the problem with the router, I started looking for another way, and found it.
On the Internet, it is recommended to use Remote Port Forwarding from SSH and it is described here https://help.ubuntu.com/community/SSH/OpenSSH/Port... Using
the same manual, I got the following
ssh -R 9001:localhost:9001 [email protected]
After this command, as I understand it, port 9001 from host.dev should be bound to my local machine. This way I have direct access to xdebug from my local machine.
As you understand, it doesn't work :(
I see errors in the xdebug logs, but googling doesn't help.

Log opened at 2017-01-29 11:22:36
I: Connecting to configured address/port: localhost:9001.
W: Creating socket for 'localhost:9001', poll success, but error: Operation in progress (29).
W: Creating socket for 'localhost:9001', poll success, but error: Operation in progress (29).
E: Could not connect to client. :-(
Log closed at 2017-01-29 11:22:36

My PHPStorm IDE is set up in the standard way.
1. Xdebug port changed
1c9e918cb38f4b068a4203725d3a30d3.png
2. DBGp Proxy configured
353b0ee8731f4dd990caaa6e5384df51.png
3. Remote server configured with mapping of local and remote directories
65bc76b5af3941fa977cc5ec59cac071.png
Since I have a multi-domain application, the server is configured for one domain. I did not find how to make it universal.
Please note that mine works on port 8080. It is this port that is forwarded from nginx listening on port 80 inside the Docker container to the host machine. Therefore, when setting up the server, I specified port 8080.
4. Configured for the PHP Remote Debug project on the server created in step 3
15dfe7c73fdc4a25a100f97a6d4537ee.png
5. Then I select the configuration and start waiting for the debug session
33ac2be675b34e66bc19837c21c8e473.png
Everything seems to be logical and correct.
And finally, the Xdebug Helper for Chrome is installed in the browser, in which debugging is enabled
141cbee88f564c00832766e1f56206a6.png
Does anyone know what's the matter?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
V
Vitaly Voskobovich, 2020-03-24
@voskobovich

Here is a detailed answer to my question.
Consider the situation from the side of a remote server running a docker container.
Docker has already taken care of most of the problem and made all the routes so that you could ping the eth0 interface from the container, through which the Internet should go to the server machine. Moreover, from the container you can ping any host on the docker host, except for 127.0.0.1 of the host itself - for obvious reasons (127.0.0.1 from the container will be the lo interface of the container itself).
Let's say the IP on eth0 of your host is 10.45.6.87. That is, the ping from the docker container to 10.45.6.87 should be successful.
And since eth0 is an exit to the outside world, then you can tell xdebug that the client will be on host 10.45.6.87 port 9000, let him wait there. We will then make an SSH tunnel there.
We create a tunnel.
We forward the remote port through the SSH tunnel to the local machine
ssh -R 9000:localhost:9000 [email protected]
and expect that in the end the bind on the remote side will look like this,
10.45.6.87:9000 => 127.0.0.1:9000
but we are very wrong :)
And this mistake costs us a lot of time.
Let's see what netstat -plnt tells us .
And he should say that after starting the tunnel, on the remote machine we have a bind at
127.0.0.1:9000 , and not 10.45.6.87:9000 as expected.
That is, it turns out that xdebug is waiting for a client at 10.45.6.87:9000, and after opening the tunnel, the client is at 127.0.0.1:9000 .
The trouble is that we can only bind the client to the local host .
That's what it says in the man ssh doc .
From the container, we cannot see 127.0.0.1:9000 of the docker host, which means that it remains only to route packets from 10.45.6.87:9000 to 127.0.0.1:9000 inside the remote machine.
This can be done in many ways, including iptables. Personally, I made another SSH tunnel inside my server like this:
1. In the xdebug configs, specify

xdebug.remote_port = 9001
xdebuh.remote_host = 10.45.6.87

2. We pass port 9000 to our local machine through the tunnel from the virtual machine.
ssh -R 9000:127.0.0.1:9000 [email protected]
3. On the local machine, we create a tunnel from port 9000 to 9001
ssh -g -L 9001:localhost:9000 -f -N 127.0.0.1
That's all.
But it is worth considering that this solution is designed for only one developer and is full of crutches.
So a couple of days after the concept of the problem, I raised the server in the docker on the same OpenVPN server and the problem disappeared by itself.
I explain. VPN creates a virtual local area network. My local machine and my virtual machine, which is located on the hosting provider's servers, are on the same local network. And if so. In this case, I can ping my local machine from a docker container running on a virtual machine. So Xdebug will connect directly to my local machine without any forwarding and crutches.
In this scenario, you can configure Xdebug in two ways.
First.
Xdebug will knock on a specific IP.
xdebug.remote_port = 9000
xdebug.remote_host = <IP локальной машины>

This is useful when you are the only developer on a project and need to debug console scripts.
Second.
Xdebug will knock on the IP from which the request came.
xdebug.remote_connect_back=1
xdebug.remote_port = 9000

Convenient when a development team is working, but not convenient when you need to debug a console script. When running the script in the console, you need to pass the IP of the developer's local machine to Xdebug so that it knows where to send the debug logs.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question