Настройка XDebug с docker container

Для меня целью было настроить первый пример связки XDebug и docker container, котрый бы работал и я мог понять что и как работает. Поиграть так сказать с настройками по пути чтения документации.

В поиске я искал наиболее простой пример, для простоты понимания. В этой статье я нашел то что мне было необходимо. https://serversforhackers.com/c/getting-xdebug-working. Это простой перевод с несколькими пояснениями о xdebug.remote_host

Начнем конфигурацию PhpStorm. Она будет состоять с двух этапов:
1. Создания Server
2. Создания новой конфигурации PHP Remote Debugger

Эти настройки выглядят так

Docker

Нам будет необходимо иметь несколько фалов для старта:

  1. Dockerfile чтоб создать image с xDebug

2. xdebug.ini файл конфигурации для xDebug

3. скрипт start-container для использования как CMD(для начала процеса контейнера)

Файл Dockerfile

FROM ubuntu:16.04

MAINTAINER Chris Fidao
RUN apt-get clean && apt-get update && apt-get install -y locales && locale-gen en_US.UTF-8

ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8

RUN apt-get update \
&& apt-get install -y curl zip unzip git software-properties-common sqlite3 \
&& add-apt-repository -y ppa:ondrej/php \
&& apt-get update \
&& apt-get install -y php7.0-fpm php7.0-cli php7.0-mcrypt php7.0-gd php7.0-mysql \
php7.0-pgsql php7.0-imap php-memcached php7.0-mbstring php7.0-xml php7.0-curl \
php7.0-sqlite3 php7.0-xdebug \
&& php -r "readfile('http://getcomposer.org/installer');" | php -- --install-dir=/usr/bin/ --filename=composer \
&& mkdir /run/php \
&& apt-get remove -y --purge software-properties-common \
&& apt-get -y autoremove \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

COPY
xdebug.ini /etc/php/7.0/mods-available/xdebug.ini

COPY start-container /usr/local/bin/start-container
RUN chmod +x usr/local/bin/start-container

EXPOSE 80
CMD ["start-container"]

Файл xdebug.ini

zend_extension=xdebug.so 
xdebug.remote_enable=1
xdebug.remote_handler=dbgp
xdebug.remote_port=9000
xdebug.remote_autostart=1
xdebug.remote_connect_back=0
xdebug.idekey=docker
xdebug.remote_host=???

Здесь самый важный момент в настройке, узнать ip-адрес хост-системы по которому контейнер сможет обращаться. На ubuntu это можно сделать следуещей командой

ip addr show

В результате вы получите данные о различных сетевых устройствах, у меня на ubuntu 18 это будет устройство wlp3s0 с адресом

192.168.1.3

Так же можно использовать адрес устройства docker0

172.17.0.1

Для того чтобы понять что это такое можно посмотреть на принцип работы xDebug на удалённом сервере

Сначала вы делаете запрос на сервер по порту 80(например откроете страницу в браузере). В ответ сервер(если установлено xdebug.remote_enable=1) пытаеться установить соеденение DBGP(xdebug.remote_handler=dbgp) по порту 9000 (xdebug.remote_port=9000) с хост системой (xdebug.remote_host=172.17.0.1).

Но если (xdebug.remote_connect_back=1) установлен в TRUE, тогда указанное значение (xdebug.remote_host) будет игнорироваться и для remote_host будет использоваться значение взятое из $_SERVER[‘HTTP_X_FORWARDED_FOR’] или $_SERVER[‘REMOTE_ADDR’]. Нам нужно указать свой remote_host поэтому нужно установить (xdebug.remote_connect_back=0)

Так же ваша хост система должна слушать порт 9000, поэтому в настройке PhpStorm мы указали слушать порт 9000.

Файл start-container

#!/usr/bin/env bash  
php -S 0.0.0.0:80 -t /var/www/html

Файл docker-compose.yml
Чтоб сделать создание и запуск контейнера легче ипользуем docker-compose

version: '2'
services:
app:
build:
context: .
image: xdebug-example:latest
volumes:
- ./app:/var/www/html
ports:
- "80:80"

Файл index.php
Создадим очень простое приложение

mkdir app 
nano app/index.php

С содержимым

<?php  
$one = 1;
$two = 2;
$three = $one + $two;
echo ($three === 3) ? '1 plus 2 equals 3!' : 'Something is terribly wrong';phpinfo();

Создание image и запуск контейнера

docker-compose build 
docker-compose up -d

Если есть подозрение на опечатку в файле xdebug.ini можно проверить совпадают ли они с данными получеными из phpinfo();
Так же перед запуском приложения у вас должен быть свободным порт 80, если у вас стоит на хост машине apache2 или nginx. Тогда остановите их командой

service apache2 stopилиservice nginx stop

Так же возможно нужно будет на хост машине открыть порт для принятия данных xDebug

sudo iptables -A INPUT -p tcp --dport 9000 -j ACCEPT