Solución de problemas con xdebug “doble” en Docker PHP
En este tema, para los usuarios con problemas de Xdebug que aparece “doble” en phpinfo() o xdebug_info(), o que no conecta bien con el IDE. Vamos a modificar algunos pasos de la instalación para ver si solucionamos el problema.
1) Dockerfile
Deja que el Dockerfile habilite Xdebug con el script oficial y no vuelvas a declarar zend_extension a mano.
# [...]
# Instalar Xdebug con PECL y habilitarlo (esto crea docker-php-ext-xdebug.ini)
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends $PHPIZE_DEPS; \
pecl install xdebug; \
docker-php-ext-enable xdebug; \
apt-get purge -y --auto-remove $PHPIZE_DEPS; \
rm -rf /var/lib/apt/lists/*
# [...]
Nada de zend_extension en el Dockerfile. Ese marrón ya lo asume docker-php-ext-enable.
2) conf.d/99-xdebug.ini
Este archivo debe tener solo directivas, sin zend_extension. Algo así:
; NO pongas zend_extension aquí
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_port=9003
; Para equipos heterogéneos suele ser mejor:
xdebug.discover_client_host=true
; Si prefieres host fijo, comenta la anterior y usa:
; xdebug.client_host=host.docker.internal
; Durante diagnóstico, súbelo:
; xdebug.log_level=7
; xdebug.log=/tmp/xdebug.log
3) Limpieza de duplicados antiguos (una vez)
Si ya venías arrastrando cosas, entra al contenedor PHP y quita cualquier ini extra que declare la extensión además del que crea ext-enable:
# Ver qué hay
docker compose exec php sh -lc 'ls -1 /usr/local/etc/php/conf.d | cat'
# Borrar el tuyo antiguo si aún tiene zend_extension
docker compose exec php sh -lc 'sed -n "1,3p" /usr/local/etc/php/conf.d/99-xdebug.ini'
# Si ves "zend_extension" ahí, elimínalo del archivo (o sustitúyelo por el contenido de arriba).
# Si por lo que sea hay otro ini casero con zend_extension, bórralo:
# docker compose exec php rm -f /usr/local/etc/php/conf.d/20-xdebug.ini
Lo normal es quedarte con:
docker-php-ext-xdebug.ini→ contiene elzend_extension=...99-xdebug.ini→ soloxdebug.*
4) (Recomendado) Para Linux
En docker-compose.yml, servicio php, mete el gateway para que “host.docker.internal” exista. Si usas discover_client_host=true puedes vivir sin esto, pero no estorba:
services:
php:
# ...
extra_hosts:
- "host.docker.internal:host-gateway"
¿Rearrancar o rebuild?
Depende de qué hayas tocado. Regla simple:
- Si cambiaste el Dockerfile (instalación/habilitación de Xdebug): necesitas rebuild de la imagen.
docker compose down
docker compose build --no-cache php
docker compose up -d
- Si solo editaste archivos
.inimontados por volumen (o copiados fuera del build): basta reiniciar el contenedor PHP para que FPM recargue INIs.
docker compose restart php
# si eres de puño de hierro:
# docker compose exec php kill -USR2 1 # reload maestro de php-fpm
No intentes rezarle a php --ini sin reiniciar FPM si cambiaste INIs dentro del contenedor; a FPM le da igual hasta que lo reinicias.
Verificación en 30 segundos
Dentro del contenedor PHP:
# 1) Ver que Xdebug está cargado en CLI
docker compose exec php sh -lc 'php -m | grep -i xdebug'
# 2) Ver que FPM carga lo mismo (no te fíes solo de CLI)
docker compose exec php sh -lc 'php-fpm -i | grep -i "xdebug.mode\|client_host\|client_port\|start_with_request\|discover_client_host"'
# 3) Si todo ok, en el navegador abre /xdebug.php con:
# <?php xdebug_info();
# y comprueba client/port y si "intentó conectar".