When i heard about debugging in PHP:
- "That's hard to do"
- "Need to write debug code using var_dump() and die() functions"
And blá-blá-blá. But we don't need it.
So let's debug PHP code without writing any debug code like var_dump(), dd() or die() inside a Docker container.
First of all, you need to have docker installed in your pc. To install docker go to docs (https://docs.docker.com/engine/installation/) and follow the steps.
After that, we need to create a Docker container with php-fpm and xdebug extension installed. For this, we can use the phpdocker.io that automatically generates a container.
It's quite simple, go to https://phpdocker.io/generator and choose your options. The options are separated in Global, PHP, Database and Zero-config configurations.
In global you only need to choose the project name, you can use "xdebug-docker", for example. In application type config use the default option (Generic: Zend, Laravel, Lumen...), for base port use 80, or any other port that you want, in this project is (:8200) and for the max upload size, you can use the default (100MB).
For PHP configuration you can choose PHP 7.1, don't need to use Git and select the XDebug extension in Extensions tab.
In database and zero-config we don't need anything. Just let them, like they are by default.
Now we need to configure the docker-compose.yaml and Dockerfile, first open the /phpdocker.io/php-fpm/Dockerfile in your editor:
FROM phpdockerio/php71-fpm:latest
WORKDIR "/application"
# Install selected extensions and other stuff
RUN apt-get update \
&& apt-get -y --no-install-recommends install php-xdebug \
&& apt-get clean; rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*
We need to put the xdebug configuration in this file. So add a slash \ after doc/* and add the follow lines:
&& echo "zend_extension=/usr/lib/php/20160303/xdebug.so" > /etc/php/7.1/mods-available/xdebug.ini \
&& echo "xdebug.remote_enable=on" >> /etc/php/7.1/mods-available/xdebug.ini \
&& echo "xdebug.remote_handler=dbgp" >> /etc/php/7.1/mods-available/xdebug.ini \
&& echo "xdebug.remote_port=9000" >> /etc/php/7.1/mods-available/xdebug.ini \
&& echo "xdebug.remote_autostart=on" >> /etc/php/7.1/mods-available/xdebug.ini \
&& echo "xdebug.remote_connect_back=0" >> /etc/php/7.1/mods-available/xdebug.ini \
&& echo "xdebug.idekey=docker" >> /etc/php/7.1/mods-available/xdebug.ini
These lines add some configurations for xdebug on PHP ini, okay thats easy to see, but what this configs really do?
-
remote_enable: if enabled, this tries to contact a client, that you can configure using remote_host and remote_port. If the connection fails, the xdebug set this to false automatically.
-
remote_handler: select the debugger output, see that in versions 2 or later this needs to be dbpg if you want to learn more about common debugger protocol see (https://xdebug.org/docs-dbgp.php).
-
remote_port: set the port for the xdebug, the default is 9000.
-
remote_autostart: If true, xdebug will attempt to start and connect to the remote host.
-
remote_connect_back: If true or 1, this will ignore the remote_host and will try to connect to client host that made the request using ($_SERVER['HTTP_X_FORWARDED_FOR'] and $_SERVER['REMOTE_ADDR']) headers.
-
idekey: Controls which IDE Key Xdebug should pass on to the DBGp debugger handler.
if you want to learn more about XDebug configuration, see https://xdebug.org/docs/all_setting.
Then build the container.
docker-compose up --build
After building the container edit the docker-compose.yml, setting the environment for php-fpm services.
For xdebug (XDEBUG_CONFIG) we need to set the remote_host, that'll be the docker container network IP address and for PHPStorm (PHP_IDE_CONFIG) we must set an environment variable "serverName", that will be the xdebug connection that IDE will be listening.
If you have doubts about how you can take your container IP see (https://linux.die.net/man/8/ifconfig) for Linux or (https://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/ipconfig.mspx) for Windows.
If you don't use PHPStorm, you don't need the PHP_IDE_CONFIG.
environment:
XDEBUG_CONFIG: remote_host=172.17.0.1 #your docker network ip.
PHP_IDE_CONFIG: "serverName=xdebug-docker" #phpstorm need a environment var that tell who xdebug connect we must to listen.
Restart your container.
docker-compose down
docker-compose up -d
For this tutorial, you can use Microsoft Visual Studio Code or JetBrains PHP Storm IDE for this tutorial.
So open your favorite editor and let's work!
In VSC, click on Debug in the menu bar or use key shortcode F5, choose PHP. The editor will create a /.vs/launch.json file. Open this file and put those configurations.
"serverSourceRoot": "/application/public",
"localSourceRoot": "${workspaceRoot}/public"
Create a main hello world script in /public/index.php:
<?php
$hello = "Hello World";
echo $hello;
To add a breakpoint in VSC, right click on the line and select "Add Column Breakpoint" or just click in the column before the line number.
Then click on the green play icon, in upper left corner, to start listening debug server.
Finally, execute http://127.0.0.1:8200 (or use the port that you have configured previous).
And it's done.
In PHPStorm go to File -> Settings -> Languages & Frameworks -> PHP -> Server. And create a server with the same name and IP that you set in you docker-compose.yml environment and set up your path mappings.
Create the main hello world script in /public/index.php:
<?php
$hello = "Hello World";
echo $hello;
To start your debug server go to Run -> Start Listening for PHP debug connections and to add a breakpoint in PHPStorm IDE just click on the column after the line number.
Execute in browser http://127.0.0.1:8200 (or use the port that you have configured previous).
And it's done.
So that's it. Now we are able to use XDebug inside a Docker container.
Cya.