Descubrir y solucionar errores en el desarrollo de aplicaciones web puede ser un desafío, pero gracias a herramientas como Xdebug y Docker, el proceso se vuelve mucho más fácil y eficiente. Xdebug, una extensión de depuración para PHP, y Docker, una plataforma de contenedores, se combinan para ofrecer a los desarrolladores un entorno de depuración poderoso y portátil.
En este post, exploraremos cómo Xdebug y Docker pueden trabajar en armonía para acelerar el desarrollo y mejorar la calidad del código. Analizaremos las ventajas de utilizar Xdebug en un entorno Dockerizado, cómo configurar la integración entre ambos y los beneficios que esto brinda a los desarrolladores.
Descubriremos cómo Xdebug permite la depuración remota de aplicaciones PHP, permitiéndonos inspeccionar variables, rastrear la ejecución del código y analizar problemas de rendimiento en tiempo real. Y al combinarlo con Docker, logramos crear entornos de desarrollo consistentes y reproducibles, independientes de la configuración del sistema operativo subyacente.
Si eres un desarrollador PHP que busca optimizar su flujo de trabajo y simplificar la depuración de aplicaciones, este post te guiará a través de los pasos para aprovechar al máximo Xdebug y Docker. Prepárate para descubrir una forma más rápida y eficiente de encontrar y corregir errores en tus proyectos web.
¿Qué es Docker?
Docker ha revolucionado la forma en que desarrollamos y desplegamos aplicaciones. Al utilizar contenedores ligeros y portátiles, Docker permite encapsular aplicaciones y sus dependencias, lo que facilita la creación de entornos de desarrollo consistentes y reproducibles. Con Docker, los desarrolladores pueden construir, distribuir y ejecutar aplicaciones de forma rápida y eficiente en cualquier entorno, sin preocuparse por las diferencias en la configuración del sistema operativo. Esta tecnología ha simplificado enormemente el desarrollo y despliegue de aplicaciones, brindando una mayor flexibilidad y escalabilidad a los proyectos.
¿Qué es Xdebug?
Xdebug es una poderosa extensión de depuración para PHP que ha cambiado la forma en que los desarrolladores resuelven problemas en sus aplicaciones. Con capacidades de depuración remota, Xdebug permite inspeccionar variables, rastrear la ejecución del código y analizar el rendimiento en tiempo real. Esta herramienta es especialmente valiosa para detectar errores y optimizar el código durante el desarrollo, brindando una mayor visibilidad y facilitando la resolución de problemas. Con Xdebug, los desarrolladores pueden mejorar la calidad de sus aplicaciones PHP y acelerar el proceso de desarrollo de software.
Beneficios de Xdebug:
-
Inspección de variables: Xdebug permite examinar el contenido de las variables en tiempo de ejecución, lo que facilita la identificación de valores incorrectos o inesperados. Esta capacidad de inspección en detalle ayuda a comprender el estado del programa y a detectar rápidamente posibles problemas.
-
Rastreo de la ejecución del código: Xdebug permite seguir el flujo de ejecución de un programa paso a paso, lo que ayuda a comprender cómo se procesa cada línea de código y a identificar cualquier desviación o error en el flujo lógico del programa.
-
Puntos de interrupción: Xdebug permite establecer puntos de interrupción en el código fuente, lo que permite detener la ejecución del programa en un punto específico y examinar el estado de las variables en ese momento. Esto es especialmente útil para identificar el origen de errores o para comprender el comportamiento de un programa en un punto crítico.
-
Depuración remota: Xdebug permite la depuración remota, lo que significa que puedes ejecutar y depurar una aplicación PHP en un servidor remoto desde tu entorno de desarrollo local. Esto facilita la identificación y solución de errores que pueden surgir en entornos de producción o en sistemas que no son directamente accesibles.
-
Perfil de rendimiento: Xdebug proporciona herramientas para el perfilado de rendimiento, lo que permite identificar cuellos de botella y áreas de mejora en el rendimiento de una aplicación. Esto es especialmente útil para optimizar el código y mejorar la eficiencia de la aplicación.
1. Creando o reutilizando un proyecto
Utilizaremos un proyecto existente en caso de que no tengamos alguno podemos seguir este tutorial para crear un blog simple aqui.
Por ejemplo podriamos crear dicho proyecto con los siguientes pasos:
- Abre tu terminal o línea de comandos.
- Ejecuta el siguiente comando para crear y ejecutar un contenedor temporal con Composer:
docker run --rm -it -v "$(pwd)":/app composer create-project symfony/skeleton blog
- El comando descargará la imagen de Composer si no está presente en tu sistema y creará el proyecto Symfony en el directorio actual.
Explicación del comando:
docker run
ejecuta un contenedor a partir de una imagen.--rm
elimina automáticamente el contenedor después de que finaliza la ejecución del comando.-it
habilita la interactividad y asigna un terminal para que puedas ver la salida y realizar interacciones dentro del contenedor.-v "$(pwd)":/app
monta el directorio actual en el contenedor en el directorio/app
. Esto asegura que el proyecto Symfony se cree en el directorio actual fuera del contenedor.composer create-project symfony/skeleton blog
es el comando que se ejecuta dentro del contenedor para crear el proyecto Symfony en el directorio “blog”.
Usualmente el comando crea el proyecto en el directorio en el que te encuentres pero dicho proyecto tiene permisos eso lo puedes corregir con el siguiente comando por fines practicos
sudo chmod 777 -R ./blog
2. Configuracion del entorno de docker para el proyecto
- Crearemos una carpeta llamada “.docker”.
- Dentro de esta carpeta crearemos el archivo “.env” con el siguiente contenido:
COMPOSE_PROJECT_NAME=blog
TIMEZONE=America/Mexico_City
- Dentro de esta carpeta crearemos el archivo “docker-compose.yml” con el siguiente contenido.
version: "3"
services:
php:
container_name: blog-php
build:
context: ./php
args:
TIMEZONE: ${TIMEZONE}
volumes:
- ../:/var/www/blog
environment:
XDEBUG_CLIENT_HOST: 172.17.0.1
XDEBUG_CLIENT_PORT: 9003
PHP_IDE_CONFIG: 'serverName=blog-debug'
nginx:
image: nginx:alpine
container_name: blog-nginx
restart: unless-stopped
ports:
- "8098:80"
volumes:
- ../:/var/www/blog
- ./nginx:/etc/nginx/conf.d
- Importante: Como puedes ver, agregamos una variable llamada “XDEBUG_CLIENT_HOST”. Esta variable y su puerto son muy importantes más adelante. Si estás usando Windows o Mac, puedes utilizar el valor “host.internal.docker”. En caso de que estés utilizando Linux, utiliza el siguiente comando para obtener dicho valor:
ip a | grep docker0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}'
- Dentro de nuestra carpeta “.docker”, crearemos una carpeta llamada “nginx”. Dentro de esta carpeta, crearemos un archivo llamado “blog-web.conf”. En realidad, podría llamarse de cualquier manera, pero hemos elegido este nombre y contendrá la siguiente configuración para nuestro servidor:
server {
listen 80;
index index.php index.html;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/blog/public;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass blog-php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
gzip_static on;
}
}
- Dentro de nuestra carpeta “.docker”, crearemos una carpeta llamada “php”. Aquí crearemos dos configuraciones y nuestro Dockerfile.
- “php.ini”, la cual contendrá toda la configuración que deseamos para nuestro servicio de PHP.
memory_limit=1024M
opcache.enable=1
opcache.revalidate_freq=10
opcache.validate_timestamps=1
opcache.max_accelerated_files=10000
opcache.memory_consumption=192
opcache.max_wasted_percentage=10
opcache.interned_strings_buffer=1
opcache.fast_shutdown=1
upload_max_filesize = 20M
post_max_size = 20M
- “xdebug.ini”, la cual contendrá toda la configuración que deseamos para la extensión Xdebug. Como se puede ver, aquí se hace uso de las variables “XDEBUG_CLIENT_HOST” y “XDEBUG_CLIENT_PORT”.
[XDebug]
zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20210902/xdebug.so
xdebug.client_host=${XDEBUG_CLIENT_HOST}
xdebug.client_port=${XDEBUG_CLIENT_PORT}
xdebug.start_with_request=1
xdebug.discover_client_host=1
xdebug.mode=develop,coverage,debug,profile
xdebug.output_dir=/tmp
xdebug.log=/dev/stdout
xdebug.log_level=0
- “Dockerfile”: Este archivo es importante y debe tener este nombre. Aquí construiremos la imagen de nuestro sistema que contendrá lo básico para ejecutar Symfony con PHP 8.1-fpm. Aquí se puede ver que se hace uso de nuestra variable previamente establecida en nuestro archivo “.env”, “TIMEZONE”:
FROM php:8.1-fpm
ARG TIMEZONE
COPY ./php.ini /usr/local/etc/php/conf.d/docker-php-config.ini
RUN apt-get update && apt-get install -y \
gnupg \
g++ \
procps \
openssl \
git \
unzip \
zlib1g-dev \
libzip-dev \
libfreetype6-dev \
libpng-dev \
libjpeg-dev \
libicu-dev \
libonig-dev \
libxslt1-dev \
acl \
&& echo 'alias sf="php bin/console"' >> ~/.bashrc
RUN docker-php-ext-configure gd --with-jpeg --with-freetype
RUN docker-php-ext-install \
pdo pdo_mysql zip xsl gd intl opcache exif mbstring
# Set timezone
RUN ln -snf /usr/share/zoneinfo/${TIMEZONE} /etc/localtime && echo ${TIMEZONE} > /etc/timezone \
&& printf '[PHP]\ndate.timezone = "%s"\n', ${TIMEZONE} > /usr/local/etc/php/conf.d/tzone.ini \
&& "date"
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/
RUN install-php-extensions xdebug-3.1.5
COPY ./xdebug.ini $PHP_INI_DIR/conf.d/xdebug.ini
WORKDIR /var/www/blog
- La estructura de nuestra carpeta “.docker” debe verse de la siguiente manera:
.
├── docker-compose.yml
├── nginx
│ └── blog-web.conf
└── php
├── Dockerfile
├── php.ini
└── xdebug.ini
3. Configuracion de docker en PHPStorm
Al ingresar a Settings > PHP, podremos ver la siguiente configuración.
Configuracion de PHP principal
Al seleccionar el CLI Interpreter, se mostrará una nueva ventana donde podremos seleccionar desde dónde ejecutar los binarios de PHP. En nuestro caso, seleccionaremos Docker.
Opcion de seleccionar nuevo interprete
Al seleccionar Docker, se nos dará la opción de qué imagen o contenedor deseamos ejecutar. Seleccionaremos “blog-php”.
Opcion de seleccionar nuevo interprete con docker
Finalmente, Docker nos mostrará las configuraciones que podemos agregar o modificar. Simplemente daremos clic en “Ok”, lo cual cerrará nuestra ventana y nos llevará de vuelta a la ventana principal.
Opcion de seleccionar nuevo interprete con docker
Es importante agregar los mappings, ya que debemos indicar a PhpStorm dónde se encuentran nuestros archivos en el servidor remoto de Docker. Esta opción nos aparece al dar clic en “Path Mappings”.
Mappings docker container
Por último, así se ve nuestra configuración.
Configuracion final
- Al ingresar a Settings > PHP > Servers, veremos que podemos agregar una configuración y crearemos la siguiente.
- Debe tener el nombre “blog-debug”
- Host “0.0.0.0”
- Port “8098”
- Habilitada la opción “Use path mappings” y establecer los mappings como se puede apreciar en la siguiente imagen.
Configuracion web Xdebug
4. Resultados
La estructura del proyecto debe ser la siguiente:
.
├── bin
│ └── console
├── config
│ ├── packages
│ │ ├── cache.yaml
│ │ ├── framework.yaml
│ │ └── routing.yaml
│ ├── routes
│ │ └── framework.yaml
│ ├── bundles.php
│ ├── preload.php
│ ├── routes.yaml
│ └── services.yaml
├── .docker
│ ├── nginx
│ │ └── blog-web.conf
│ ├── php
│ │ ├── Dockerfile
│ │ ├── php.ini
│ │ └── xdebug.ini
│ ├── docker-compose.yml
│ └── .env
├── public
│ └── index.php
├── src
│ ├── Controller
│ │ └── .gitignore
│ └── Kernel.php
├── var
├── composer.json
├── composer.lock
├── .env
├── .gitignore
└── symfony.lock
- Debemos ingresar a la carpeta “.docker” y ejecutar el comando “docker-compose up -d” o “docker-compose up -d”. La salida debe ser similar a la siguiente:
-
Nota: La primera vez que lo ejecutes, construirá las imágenes y probablemente tardará.
-
Al ingresar a la URL http://localhost:8098, podremos ver la página inicial de Symfony.
-
Agregaremos un punto de interrupción (breakpoint) y al recargar el sitio, podemos ver que PhpStorm detiene la ejecución en el punto determinado.
-
Podremos ver las variables del servidor de entorno y realizar operaciones en el punto de interrupción (breakpoint).
- Agregaremos un punto de interrupción (breakpoint) y al ejecutar un comando desde el contenedor, este también se detendrá.
Conclusión
La combinación de Docker, Xdebug y PhpStorm proporciona un entorno de desarrollo altamente eficiente y productivo para proyectos PHP. Docker garantiza la portabilidad y el aislamiento de la aplicación, mientras que Xdebug facilita la depuración con la capacidad de establecer puntos de interrupción y rastrear el flujo de ejecución. PhpStorm ofrece una interfaz intuitiva y herramientas integradas para aprovechar al máximo las capacidades de Docker y Xdebug, lo que permite un desarrollo fluido, ágil y sin problemas. En conjunto, estas herramientas mejoran la productividad, facilitan la colaboración en equipo y agilizan la identificación y solución de errores, lo que resulta en un flujo de trabajo de desarrollo más eficiente y un desarrollo de calidad para aplicaciones PHP.
Como adicional, con la configuración que hemos creado, no es necesario crear una configuración para cada comando, ya que detectará cualquier punto de interrupción (breakpoint) que le agreguemos debido a las claves que configuramos en el archivo docker-compose.yml.
El repositorio de este post lo podrás encontrar en: https://github.com/gouh/Docker-PHPStorm-Xdebug.