Как организовать отладку PHP-скрипта на удалённом сервере, где PHP запущен внутри Docker-контейнера?

Как настроить и отлаживать такой CLI-скрипт в PhpStorm? Кто уже настраивал — поделитесь, пожалуйста, своими настройками.
  • 26 февраля 2026 г. 21:01
Ответы на вопрос 2
Коротко: всё делается через Xdebug + корректные path‑mapping в PhpStorm + способ доставить соединение от Xdebug (в контейнере на удалённом хосте) до вашего IDE (либо IDE доступна напрямую по ip, либо делаете SSH‑туннель). Ниже — рабочая инструкция с примерами и подсказками для типичных вариантов.

1) Установите/включите Xdebug в контейнере
- Убедитесь, что в контейнере стоит Xdebug (php -v / php -m). Желательно Xdebug 3.
- Пример конфигурации для Xdebug 3 (php.ini / conf.d/xdebug.ini):
  xdebug.mode=debug
  xdebug.start_with_request=trigger    ; безопаснее — включать по триггеру
  xdebug.client_host=127.0.0.1        ; см. секцию про network ниже
  xdebug.client_port=9003
  xdebug.idekey=PHPSTORM
  xdebug.log=/tmp/xdebug.log
  xdebug.log_level=0

Примечание: start_with_request можно ставить "yes" (все запросы будут пытаться подключаться к IDE) или "trigger" (тогда нужно выставлять XDEBUG_TRIGGER или cookie/GET).

2) Как заставить Xdebug достучаться до PhpStorm (remote networking)
Есть два варианта:
A) IDE имеет публичный/доступный IP для контейнера:
- Установите xdebug.client_host=<IP вашей машины>, xdebug.client_port=9003 и откройте порт 9003 на вашей машине/файрволе.
- Менее безопасно и часто не возможно (NAT, корпоративные сети).

B) Рекомендуемый вариант — SSH reverse tunnel (самый надёжный, если удалённый сервер под вашим контролем):
- На локальной машине (там, где PhpStorm) выполните:
  ssh -N -R 9003:localhost:9003 user@remote.host
  (параметр -N — без shell, -R создаёт прослушивание на удалённом хосте; если нужно слушать не только на loopback удалённого — используйте -R 0.0.0.0:9003:localhost:9003 и включите GatewayPorts в sshd_config на удалённом сервере)
- Тогда в контейнере (на удалённом) xdebug.client_host можете указывать 127.0.0.1 (или адрес удалённого хоста), и трафик попадёт в локальный PhpStorm.

3) CLI-скрипты: как запускать и триггерить дебаг
- Если в ini установлен start_with_request=trigger, то делайте:
  docker exec -it my_php_container bash
  export XDEBUG_TRIGGER=PHPSTORM
  php /path/to/script.php
  либо в одну строку:
  XDEBUG_TRIGGER=1 php /path/to/script.php
- Можно также временно переопределять параметры при запуске:
  docker exec -it my_php_container php -d xdebug.mode=debug -d xdebug.client_host=127.0.0.1 /path/to/script.php
- Для Xdebug 3 можно использовать env-переменные:
  XDEBUG_MODE=debug XDEBUG_CONFIG="client_host=127.0.0.1 idekey=PHPSTORM" php script.php

4) Настройки PhpStorm
- Включите "Start Listening for PHP Debug Connections" (иконка телефончика в правом верхнем углу).
- Settings | Languages & Frameworks | PHP | Debug:
  - Debug port = 9003 (или порт, который вы используете)
  - Can accept external connections = включено (как правило по умолчанию)
- Настройте Server:
  - Settings | PHP | Servers — Add:
    Name: имя (важно: при использовании remote interpreter PhpStorm может подставлять имя)
    Host: remote.host (для URL или просто имя)
    Port: 80/443 или как у вас
    Use path mappings: задайте соответствие между локальными путями проекта и путями внутри контейнера (/var/www/html и т.п.)
  Path mappings — обязательны! Для CLI‑скрипта PhpStorm должен знать, как файлы в контейнере соответствуют локальным.
- Remote PHP Interpreter (если хотите, чтобы PhpStorm запускал CLI скрипт автоматически в контейнере):
  Settings | PHP | CLI Interpreters -> Add -> From Docker / Docker Compose (или Remote via SSH)
  - Добавьте Docker connection (если Docker удалённый — подключение по SSH/TCP к Docker API).
  - Выберите контейнер/образ и путь к php‑бинарю (/usr/local/bin/php).
  После этого можно создать Run/Debug Configuration -> PHP Script -> указать локальный файл и выбрать этот интерпретер. При запуске PhpStorm запустит php в контейнере и корректно подставит path mapping.

5) Пример docker-compose (Xdebug 3)
version: "3"
services:
  php:
    image: php:8.1-cli
    volumes:
      - ./:/var/www/html
    environment:
      XDEBUG_MODE: debug
      XDEBUG_CONFIG: "client_host=127.0.0.1 client_port=9003 idekey=PHPSTORM"
    # не обязательно открывать порт 9003 наружу, контейнер делает исходящее соединение

6) Отладка шаг за шагом (чеклист)
- В контейнере включён Xdebug и он виден (php -i | grep xdebug).
- PhpStorm слушает на порту 9003.
- Если используете SSH‑туннель — туннель поднят (на локале netstat -lpn | grep 9003, на удалённом — netstat -lpn | grep 9003 показывает прослушивание).
- Path mappings в PhpStorm соответствуют реальным путям в контейнере.
- Запустите CLI скрипт с XDEBUG_TRIGGER=1 или с переопределённым client_host.
- Поставьте breakpoint в PhpStorm — выполнение остановится в точке.

7) Диагностика проблем
- Посмотрите /tmp/xdebug.log (путь из xdebug.log) — там видно попытки соединения и ошибки.
- Убедитесь, что контейнеру разрешено делать исходящие TCP соединения на порт 9003.
- Если соединение устанавливается, но PhpStorm не показывает breakpoint — проверьте path mapping.
- В PhpStorm включите «Validate connection» в настройках сервера (там можно проверить IDE key и путь).

8) Полезные советы / нюансы
- Xdebug 2 и Xdebug 3 конфигурируются по-разному — примеры выше для 3 версии.
- Для одноразовых запущенных скриптов удобно использовать XDEBUG_TRIGGER, чтобы не менять ini.
- Если у вас CI/продакшн — не включайте start_with_request=yes в постоянном конфиге.
- Можно также использовать PhpStorm + Remote Interpreter через SSH: PhpStorm сам подключится по SSH на сервер и запустит php в контейнере (через docker exec) — это упрощает запуск, но всё равно Xdebug должен дойти до IDE (или использовать ту же SSH‑связь для проброса).

Если нужно — могу прислать:
- конкретные примеры php.ini и docker-compose для вашего случая,
- точные шаги для настройки Docker remote в PhpStorm (скриншоты/путь в меню),
- пример Run/Debug конфигурации для PHP Script.

Скажите, какая у вас версия Xdebug и как вы подключаетесь к удалённому серверу (SSH? VPN?), и я подгоню команды и конфигурации под ваш случай.
Единственное отличие для докера, это указать xdebug, что подключаться нужно к хосту. Таким образом: 
client_host=host.docker.internal
И разрешить контейнеру подключаться к хосту (со всеми вытекающими, т.е. изоляции теперь нет). Для compose примерно так:
extra_hosts:
      - "host.docker.internal:host-gateway"

Все остальное также, как и без докера.
Похожие вопросы