Как отладить PHP скрипт в Windows 10 с помощью PHPStorm и xDebug внутри docker-контейнера находящимся на сервере за NAT?

Вопрос отладки PHP-скриптов будоражит умы многих разработчиков. Так же эта инструкция поможет и тем, кто Docker не использует. На самом деле всё очень просто, достаточно прокинуть порт с удалённого сервера на локальный (так называемый remote port forwarding или ssh tunnel), делается это одной командой, но требует предварительной правки конфигов. Начнём. На удалённом сервере нужно поправить конфиг sshd:

nano /etc/ssh/sshd_config

И добавляем в него строку:

GatewayPorts clientspecified

Здесь clientspecified позволяет клиенту самостоятельно выбирать адрес для туннелирования, вместо него можно написать просто yes, тогда порт будет вешаться на локальный адрес 0.0.0.0. Без указания этой опции порт будет биндиться на хостовый адрес 127.0.0.1 и вы не сможете использовать его изнутри docker-контейнера. После чего перегружаем конфиг:

service sshd reload

Как пробросить порт на удалённый сервер?

Теперь приступаем к пробросу порта. Я использую такую команду:

ssh -i /keys/id_rsa -R 172.100.0.1:9001:localhost:9000 -N user@server

Запускать нужно на клиенте, в моём случае это Windows 10 с терминалом MobaXterm. Для других терминалов команда может немного отличаться. Опция -i указывает на файл с ключом для авторизации. Опция -R отвечает за remote port forwarding, здесь 172.100.0.1 это адрес по которому хостовая машина будет слушать порт. Затем указывается порт, который будет прослушиваться на сервере, в данном случае это 9001.

Далее указан локальный адрес localhost и локальный порт 9000. Опция -N очень удобна именно для проброса порта,  благодаря ей будет SSH будет только пробрасывать порт, не давая доступа к консоли удалённого сервера.

Пока будет запущена команда, на удалённом сервере будет прослушиваться 9001 порт и все данные и соединения будут туннелироваться на локальную машину и будут доступны по 9000 порту.

Проверить пробросился ли порт можно командой:

netstat -tulpn

Проброс порта через два сервера

Допустим, нужно подключиться к серверу для отладки, но прямого коннекта к этому серверу нет, например, из-за злоебучего росануснадзора, ебать бы этих пидоров арматурой. Тогда только остаётся найти промежуточный сервер к которому можно подключиться с рабочей станции, а также с которого можно подключиться на требуемый для отладки сервер. Для Cygwin делается это чуть сложнее.

ssh -N -R 172.20.0.1:9001:localhost:9000 root@target

Однако, предварительно нужно внести правки в файл ~/.ssh/config:

Host *
  ServerAliveCountMax 4
  ServerAliveInterval 15
  ForwardAgent yes
Host target
  HostName target.hostname
  User root
  ProxyCommand ssh [email protected] -W %h:%p

Установка и настройка xDebug в docker-контейнере

yum install php-xdebug -y
nano /etc/php.d/15-xdebug.ini
zend_extension=xdebug.so
xdebug.remote_autostart=1
xdebug.remote_enable=1
xdebug.remote_host=172.100.0.1
xdebug.remote_port=9001
xdebug.idekey="PHPSTORM"
# xdebug.remote_connect_back=1
xdebug.remote_handler=dbgp
xdebug.remote_mode=req

Обратите внимание на значения xdebug.remote_host и xdebug.remote_port. Их значения должны указывать на прослушиваемый корт хостовой системы. Также обратите внимание на директиву xdebug.remote_connect_back, она должна быть отключена либо иметь значение 0. Иначе значения remote_host и remote_port будут игнорироваться, а вместо них использоваться IP, от которого пришел запрос. После чего перезагружаем настройки php-fpm:

kill -USR2 1

Проверяем, что модуль xdebug подключен:

php -m | grep xdebug
php-fpm -m | grep xdebug

Настройка PHP Storm для отладки скрипта в Docker

В принципе, настройка IDE идентична настройкам для обычной отладки скриптов.