После предыдущих приключений с Gitlab-CI и кастомизацией Visual Studio Code как IDE для PHP мне захотелось иметь переносимую среду разработки с использованием PHP, чтобы не настраивать среду на рабочей машине, точнее чтобы любой человек мог подключится к разработке проекта с минимальными усилиями по организации среды. Так начались новые приключения ...
В итоге получится запускать скрипты в docker контейнере, а дебажить их на хостовой машине с использованием VS Code.
Репозиторий с демкой прилагается.
.vscode
- директория с конфигами для VS Code
launch.json
- конфиг для отладкиconfig
- директория с конфигами для docker образа
php.ini
- конфиг php
xdebug.ini
- конфиг xdebug
app.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 вполне работоспособна.