После предыдущих приключений с Gitlab-CI и кастомизацией Visual Studio Code как IDE для PHP мне захотелось иметь переносимую среду разработки с использованием PHP, чтобы не настраивать среду на рабочей машине, точнее чтобы любой человек мог подключится к разработке проекта с минимальными усилиями по организации среды. Так начались новые приключения ...
В итоге получится запускать скрипты в docker контейнере, а дебажить их на хостовой машине с использованием VS Code.
Репозиторий с демкой прилагается.

.vscode - директория с конфигами для VS Code
launch.json - конфиг для отладкиconfig - директория с конфигами для docker образа
php.ini - конфиг phpxdebug.ini - конфиг xdebugapp.php - скрипт для теста отладкиdocker-compose.yml - конфиг для композиции контейнеров, но мы будем использовать единственный контейнерDockerfile - конфиг нашего образа phpЧтобы отлаживать PHP скрипты в VS Code для него необходимо установить расширение php-debug, затем в .vscode/launch.json запишем:
{
"version": "0.2.0",
"configurations": [
{
"name": "Listen for Xdebug",
"type": "php",
"request": "launch",
"hostname": "172.17.0.1",
"port": 9003,
"log": true,
"pathMappings": {
"/var/www/html/": "${workspaceFolder}/",
},
"xdebugSettings": {
"max_children": 9999,
"show_hidden": 1
}
}
]
}
Кратко: указываем хост и порт, который должен слушать дебагер VS Code для получения отладочной информации, так же указываем сопоставление путей с контейнера на хосте (pathMappings). Дополнительно почитать про отладку в VS Code можно в доке.
Хост и порт должны быть такими же как у контейнера, в котором будем производить отладку.
Схема работы отладки будет такая:
В минимальном варианте нам надо 2 файла:
php.ini:[PHP]
# уровень ошибок
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
# разрешаем логирование ошибок
log_errors = On
# определяем статический путь для файла ошибок
error_log = /var/www/html/logs/php_errors.log
xdebug.ini:# определяем статический лог файл
xdebug.log=/var/www/html/logs/xdebug.log
# хост и порт клиента отладчика, с которым xdebug будет вести общение
xdebug.client_host = host.docker.internal
xdebug.client_port = 9003
# режим отладки и покрытия кода тестами
xdebug.mode=coverage,debug
# старт xdebug при выполнении PHP скрипта
xdebug.start_with_request = yes
Ложим их в директорию config.
host.docker.internal- это хост контейнера с php, который мы позже определим. Кратко: он нужен чтобы xdebug открывал с ним соединение и направлял туда отладочные данные.
Для примера будем собирать свой образ на основе php:7.4-cli (схема работоспособна и для fpm), скопируем внутрь конфиги PHP и XDebug, также установим xdebug:
FROM php:7.4-cli
COPY config/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini
COPY config/php.ini /usr/local/etc/php/conf.d/php.ini
RUN apt update \
&& pecl install xdebug && docker-php-ext-enable xdebug \
&& mkdir /var/www/html/logs && chown www-data:www-data /var/www/html/logs
WORKDIR /var/www/html/
В качестве рабочей директории будем использовать путь /var/www/html/, там будет находится корень нашего проекта.
Здесь же мы создаем директорию /var/www/html/logs и меняем ее владельца на www-data. В нее мы будем складывать все логи, и если надо ее можно прокидывать на хост машину, а владельца меняем чтобы не конфликтовать.
Теперь можно собирать образ контейнера, назовем его php с тегом debug:
docker build -t php:debug .
Создадим файл app.php со следующим содержимым:
$var = 10;
// здесь поставим breakpoint
echo "Hello world from Docker container!";
Запускаем отладчик в VS Code.
Исходники будем монтировать из хоста в контейнер, чтобы иметь возможность менять код без пересборки контейнера.
Затем можно запустить контейнер:
docker run -it \
--add-host=host.docker.internal:172.17.0.1 \
--ip=172.17.0.1 \
--expose 9003 \
-v $PWD/app.php:/var/www/html/app.php \
php:debug \
/bin/bash -c "php -f app.php"
И тут же попадем на первый поставленный breakpoint - отладка работает!
Немного подробностей:
--add-host - добавить хост в контейнер host.docker.internal с ip адресаом 172.17.0.1--ip - назначить статический ip адрес контейнеру--expose - предоставить доступ к 9003 порту контейнера (сюда будет подключаться отладчик VS Code)-v - монтирование файлов внутрь контейнераphp:debug - запускаемый образ/bin/bash -c "php -f app.php" - команда на выполнениеЭто необязательно, но для полноты картины напишем docker-compose.yml чтобы провести эксперимент и через docker-compose:
version: '3.7'
services:
php-debug:
image: php:debug
extra_hosts:
- "host.docker.internal:172.17.0.1"
volumes:
- ./app.php:/var/www/html/app.php
command: /bin/bash -c "php -f app.php"
networks:
- app_net
networks:
app_net:
driver: bridge
ipam:
driver: default
config:
- subnet: "172.17.0.1/24"
Как и в предыдущем шаге поставим breakpoint в* VS Code* и запустим docker compose:
docker compose up
Подобное приходилось настраивать и в контексте работы с CMS (разработка модуля для CMS в docker контейнерах, о чем поговорим в следующих статьях) и это оказывается удобно и просто. Удаленная отладка с xdebug вполне работоспособна.