Используем Xdebug вместе с Docker и PHPStorm

В этой статье мы рассмотрим настройку Xdebug в Docker окружении и подключение PHPStorm

Автор . Дата: 20.03.2019

Xdebug это очень полезное средство для отладки и профилирования при php разработке. С его помощью, и при использовании IDE, вы можете делать точки остановки в IDE, смотреть содержимое любых переменных и объектов, пошагово выполнять ваш скрипт. Многие php разработчики по старинке используют var_dump или var_export, и не используют отладку в IDE. Возможно это связано с проблемами настройки всей кухни, или просто старыми привычками. Первую проблему мы попытаемся сейчас решить, со второй вам придется бороться лично :-) Итак.

Docker

Для начала нам необходимо произвести настройку Docker контейнеров. За основу мы возьмем скрипты, которые были рассмотрены в прошлой статье. Расширение xdebug уже было установлено в наш контейнер, но если вдруг в вашем контейнере его нет, сделать это можно в пару команд в Dockerfile:

RUN pecl install xdebug \
    && docker-php-ext-enable xdebug

Обычно этого хватает, но бывают ситуации, когда выходит новая версия PHP, а xdebug расширение не успевает обновиться. Тогда приходится подключать альфа или бетта версию расширение. Актуальную версию для новой версии PHP вы можете узнать на сайте https://xdebug.org/

После подключения расширения, необходимо добавить настройки. Откроем файл docker/php/docker-php-entrypoint и после строки:

CONFD_PATH=$(php --ini | grep 'Scan for additional' | sed -- 's/^.*:\s*\([^ ].*\)$/\1/')

Добавим:

echo "xdebug.remote_enable=$XDEBUG_REMOTE_ENABLE" > $CONFD_PATH/xdebug_remote.ini
echo "xdebug.remote_autostart=$XDEBUG_REMOTE_AUTOSTART" >>  $CONFD_PATH/xdebug_remote.ini
echo "xdebug.remote_port=$XDEBUG_REMOTE_PORT" >> $CONFD_PATH/xdebug_remote.ini
echo "xdebug.remote_host=$XDEBUG_REMOTE_HOST" >> $CONFD_PATH/xdebug_remote.ini
echo "xdebug.idekey=$XDEBUG_IDEKEY" >> $CONFD_PATH/xdebug_remote.ini
echo "xdebug.remote_log=/var/log/container/xdebug_remote.log" >> $CONFD_PATH/xdebug_remote.ini
echo "xdebug.remote_connect_back=$XDEBUG_REMOTE_CONNECT_BACK" >> $CONFD_PATH/xdebug_remote.ini

Тут мы используем переменные окружения, для того, чтобы можно было менять какие-то параметры другим разработчикам не влезая в файлы докера. Поэтому нам необходимо передать эти переменные через Docker Compose. Для этого, в docker-compose.yml, в настройки контейнера php добавим блок параметров environment:

    environment:
      XDEBUG_REMOTE_ENABLE: ${XDEBUG_REMOTE_ENABLE}
      XDEBUG_REMOTE_AUTOSTART: ${XDEBUG_REMOTE_AUTOSTART}
      XDEBUG_REMOTE_HOST: ${XDEBUG_REMOTE_HOST}
      XDEBUG_REMOTE_PORT: ${XDEBUG_REMOTE_PORT}
      XDEBUG_IDEKEY: ${XDEBUG_IDEKEY}
      XDEBUG_REMOTE_CONNECT_BACK: ${XDEBUG_REMOTE_CONNECT_BACK}

В итоге настройка php контейнера будет выглядить вот так:

  php:
    build: ./docker/php
    working_dir: /app
    volumes:
      - ./:/app
      - ./docker/log:/var/log/container
    environment:
      XDEBUG_REMOTE_ENABLE: ${XDEBUG_REMOTE_ENABLE}
      XDEBUG_REMOTE_AUTOSTART: ${XDEBUG_REMOTE_AUTOSTART}
      XDEBUG_REMOTE_HOST: ${XDEBUG_REMOTE_HOST}
      XDEBUG_REMOTE_PORT: ${XDEBUG_REMOTE_PORT}
      XDEBUG_IDEKEY: ${XDEBUG_IDEKEY}
      XDEBUG_REMOTE_CONNECT_BACK: ${XDEBUG_REMOTE_CONNECT_BACK}
    depends_on:
      - db
    networks:
      - project

И добавляем объявление переменных в файл .env:

XDEBUG_REMOTE_ENABLE=1
XDEBUG_REMOTE_AUTOSTART=1
XDEBUG_REMOTE_HOST=host.docker.internal
XDEBUG_REMOTE_PORT=9000
XDEBUG_IDEKEY=PHPSTORM
XDEBUG_REMOTE_CONNECT_BACK=0

Из важного, здесь переменная XDEBUG_REMOTE_HOST. Она определяет ip адрес или доменное имя, куда xdebug будет отсылать отладочную инфу. В ней должен быть адрес хостовой машины в Docker сети. В случае Windows и MacOS можно оставить host.docker.internal, но говорят, что на Linux есть проблемы с этим доменным именем. Я точно не могу сказать, нет возможности проверить, если кто-то будет запускать на Linux системах, просьба отписаться в комментариях о результатах.

Так же необходимо в настройки виртуального хоста nginx добавить отправку заголовка Host на PHP. Для этого в файл docker/nginx/vhost.conf в локейшен ~ \.php$ добавьте:

fastcgi_param SERVER_NAME localhost;

 В итоге блок должен выглядеть следующим образом:

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param SERVER_PORT $server_port;
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        fastcgi_read_timeout 300;
        fastcgi_param SERVER_NAME localhost;
    }

Остался последний штрих, пересобрать контейнер:

docker-compose build

И можно запускать наш проект:

docker-compose up -d

PHPStorm

Теперь настроим PHPStorm для работы с xdebug. Заходим в настройки через меню File -> Settings. Разворачиваем вкладку Building, Execution, Deployment и выбираем вкладку Docker. Жмем плюсик и заполняем поля как указано на скриншоте.

Добавьте диски в Path mappings, если код вашего проекта расположен в ином месте, чем указано там. Например, код своих проектов я держу на диске D.

Если у вас PHPStorm не поддерживает Unix сокеты как у меня (ОС Windows), необходимо будет разрешить TCP подключения в докере. Для этого открываем настройки докера, выбираем вкладку General, и в пункте Expose daemon on tcp://localhost:2375 without TLS ставим галочку:

После этого PHPStorm должен нормально подключаться к докеру. Теперь нужно добавить интерпретатор PHP. Для этого в настройках заходим во вкладку Languages & Frameworks -> PHP, в поле Cli Interpreter, справа, жмем на кнопку с тремя точками. В открывшемся окне жмем плюсик, выбираем From Docker, Vagrant, VM, Remove. В появившемся окне выбираем Docker compose, наш добавленный ранее сервер Docker и сервис PHP.

Жмем OK и ждем некоторое время, пока будут произведены все необходимые действия.

Теперь переходим во вкладку Languages & Frameworks -> PHP -> Servers и жмем плюсик, чтобы добавить новый сервер. В поле Name обязательно указываем localhost (дело в том, что PHPStorm выбирает сервер сервер по полю, которое передает xdebug, а он формирует его на основе SERVER_NAME, которое передает nginx в php). В поле Host указываем localhost, в поле Port указываем тот порт, на котором находится ваш веб сервер. В списке Debugger выбираем Xdebug. Ставим галочку в пункте Use path mapping и для корневой папки проекта указываем маппинг на папку /app. Чтобы изменения в маппинге сохранились, необходимо нажать Enter после редактирования, в других случаях значение поля сбрасывается.

Жмем OK, и на этом настройку можно считать законченной.

Отладка

Чтобы перевести PHPStorm в режим прослушивания подключений от Xdebug, на панели в правом верхнем углу необходимо нажать на кнопку с телефонной трубкой:

После активации красный кружок в иконке пропадет, что означает, что PHPStorm ожидает информации от xdebug. Можно устанавливать точки остановки и проверять функционал :-)

Скачать код проекта можно здесь: https://github.com/lan143/docker-yii2

Приятной отладки :-)