Exponer métricas PHP‑FPM para Prometheus con exporter en Docker Compose (tutorial)

Docker & Containers · Por · Publicado el · 7 min de lectura

Primer plano de hoja verde mostrando nervaduras paralelas y textura
Fondo limpio y neutro, ideal para destacar tutorial técnico Foto: hankaverzichova / Pixabay

Tutorial: exponer métricas de PHP‑FPM a Prometheus usando un exporter en Docker Compose. Activarás el status de PHP‑FPM, levantarás un exporter dedicado y configurarás Prometheus para recolectar las métricas. Al final validamos con curl y desde la UI de Prometheus, además de dar consejos para múltiples pools y seguridad.

Arquitectura: cómo funciona el scraping

PHP‑FPM expone estadísticas en pm.status_path. Un exporter traduce esos datos al formato de Prometheus y los publica en /metrics. Prometheus hace el scrape de ese endpoint de forma periódica. Todo se ejecuta en contenedores separados orquestados por Docker Compose.

Esta separación facilita aislar responsabilidades, aplicar límites y evolucionar cada componente sin acoplamiento. A continuación los roles y puertos por defecto:

Componente Puerto Rol
php-fpm 9000/TCP Ejecuta el pool PHP y expone /status vía FastCGI
php-fpm-exporter 9253/TCP Se conecta a /status y sirve /metrics
prometheus 9090/TCP Hace el scrape del exporter y almacena series temporales

Prerequisitos y avisos importantes

Antes de comenzar necesitas Docker y Docker Compose instalados y acceso al terminal. Este paso a paso usa imágenes oficiales y configuraciones mínimas pensadas para desarrollo o laboratorio.

- Atención: el status de PHP‑FPM no tiene autenticación. Mantén el acceso restringido a la red interna de Docker o localhost. No publiques /status en Internet.

- Atención: mapear puertos públicos expone servicios. Prefiere enlazar a 127.0.0.1 durante las pruebas.

  • Docker y Docker Compose instalados
  • Permisos para ejecutar docker compose
  • Puertos 9090 y 9253 libres en la máquina local (o ajusta)
  • Conocimientos básicos de YAML y Linux

Estructura de carpetas del proyecto

Crearemos dos carpetas para separar la configuración de PHP‑FPM y Prometheus. Los archivos se irán rellenando en las secciones siguientes.

Estructura sugerida:

  • - php-fpm/www.conf
  • - prometheus/prometheus.yml
  • - docker-compose.yml
mkdir -p php-fpm prometheus
ls -la
# Depois, criaremos os arquivos nas seções seguintes com o conteúdo correto.

Habilitar el status de PHP‑FPM (pm.status_path)

El exporter depende del endpoint de status de PHP‑FPM. Activa pm.status_path y asegúrate de que PHP‑FPM escuche en TCP (puerto 9000) para facilitar la comunicación entre contenedores.

Guarda el archivo siguiente como php-fpm/www.conf.

[www]
user = www-data
group = www-data

; Ouça em TCP para facilitar a conexão do exporter
listen = 9000

; Gerenciador de processos
pm = dynamic
pm.max_children = 20
pm.start_servers = 2
pm.min_spare_servers = 2
pm.max_spare_servers = 4

; Endpoints internos do FPM
pm.status_path = /status
ping.path = /ping

; Logs para stdout/stderr do container
access.log = /proc/self/fd/2
clear_env = no

Docker Compose: php-fpm y php-fpm-exporter

Ahora orquestaremos PHP‑FPM y el exporter. El exporter hipages/php-fpm_exporter se conecta a /status vía FastCGI y sirve métricas HTTP en el puerto 9253.

Observación: el mapeo de puertos puede cambiarse a 127.0.0.1:PUERTO si quieres restringir el acceso solo al host local.

version: "3.8"
services:
  php-fpm:
    image: php:8.2-fpm-alpine
    container_name: php-fpm
    volumes:
      - ./php-fpm/www.conf:/usr/local/etc/php-fpm.d/www.conf:ro
    expose:
      - "9000"

  php-fpm-exporter:
    image: hipages/php-fpm_exporter:latest
    container_name: php-fpm-exporter
    command:
      - --phpfpm.scrape-uri=tcp://php-fpm:9000/status
      - --web.listen-address=:9253
    ports:
      - "9253:9253"   # use 127.0.0.1:9253 para restringir ao host local
    depends_on:
      - php-fpm

Prometheus: scrape del exporter

Con el exporter sirviendo /metrics, configura Prometheus para recolectar periódicamente. Usaremos un job dedicado con target apuntando al servicio exporter en Compose.

Guarda el archivo siguiente como prometheus/prometheus.yml y añade el servicio prometheus al Compose.

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: "phpfpm"
    static_configs:
      - targets: ["php-fpm-exporter:9253"]
        labels:
          instance: "app-php-fpm"

Levantar los contenedores y validar las métricas

Es hora de levantar todo y comprobar. Añade/actualiza docker-compose.yml con Prometheus, inicia los servicios y verifica que /metrics devuelve datos. También revisa los targets en la UI de Prometheus.

Consejo: si quieres dashboards, consulta cómo configurar Prometheus y Grafana en Docker Compose en cómo configurar Prometheus y Grafana.

# Acrescente o serviço Prometheus no docker-compose (separado ou no mesmo arquivo)
cat >> docker-compose.yml <<'EOF'

  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
    ports:
      - "9090:9090"   # use 127.0.0.1:9090 para restringir ao host local
    depends_on:
      - php-fpm-exporter
EOF

# Subir o ambiente
docker compose up -d

# Verificar containers
docker compose ps

# Validar métricas do exporter
curl -s http://localhost:9253/metrics | head -n 20

# Conferir algumas séries esperadas
curl -s http://localhost:9253/metrics | grep -E 'phpfpm_(up|listen_queue|processes)'

# UI do Prometheus (navegador): http://localhost:9090/targets
# Status deve aparecer como UP para o job "phpfpm".

Buenas prácticas, múltiples pools y próximos pasos

Para cada instancia/pool de PHP‑FPM, lo más simple es ejecutar un exporter por target y añadir todos en Prometheus (varios targets en el mismo job). Evita exponer /status públicamente: mantén la comunicación restringida a la red interna de Docker.

Algunas recomendaciones prácticas:

  • Restringe puertos: mapea a 127.0.0.1:9253 y 127.0.0.1:9090 cuando sea posible.
  • Mantén pm.status_path habilitado solo donde el exporter lo necesite. En producción, no lo publiques vía HTTP externo.
  • Usa labels coherentes (instance, service, env) en Prometheus para facilitar dashboards.
  • Crea alertas para cola de listen alta y procesos ocupados persistentes.
  • Optimiza pm.* del FPM según la carga; las métricas ayudan a validar el tuning. Ver: fuga de memoria en PHP‑FPM (/es/fuga-memoria-php-fpm).
  • Para visualización, conecta Prometheus a Grafana. Compara stacks en /es/comparativa-prometheus-grafana-vs-loki-tempo-php y complementa con logs centralizados (Fluentd + Elasticsearch: /es/fluentd-elasticsearch-logs-php-vps).

Errores comunes y cómo diagnosticar rápidamente

Algunos problemas aparecen con frecuencia durante la configuración inicial. Revisa las causas típicas y correcciones directas a continuación.

  • Conexión rechazada en el exporter: confirma que php-fpm está escuchando en 9000 y el nombre del servicio (tcp://php-fpm:9000/status).
  • 404 en /status: verifica pm.status_path en www.conf y reinicia el FPM (recrea el contenedor).
  • Exporter UP pero métricas vacías: revisa permisos y que el pool activo sea [www].
  • Target DOWN en Prometheus: prueba curl desde el host de Prometheus; si funciona enlazando a 127.0.0.1, ajusta la red/ports.
  • Listen_queue alta y persistente: indica saturación; ajusta pm.max_children e investiga cuellos de botella de CPU/IO.

Preguntas frecuentes

¿Puedo usar socket UNIX en lugar de TCP para PHP‑FPM?

Sí. El exporter puede comunicarse por FastCGI vía socket. Apunta --phpfpm.scrape-uri al path del socket, por ejemplo unix:///usr/local/var/run/php-fpm.sock, y monta el socket en el contenedor del exporter. En Compose, usa volúmenes compartidos entre php-fpm y el exporter.

¿Es seguro exponer /metrics del exporter en Internet?

Evítalo. Expón /metrics solo internamente (red de Docker o 127.0.0.1) y deja que Prometheus recolecte localmente. Si necesitas acceso remoto, añade autenticación y restricciones de IP en un proxy delante del exporter o accede vía VPN.

¿Cómo monitorizar varios pools o servicios PHP‑FPM?

Ejecuta un exporter por instancia/pool y añádelos como targets en Prometheus dentro del mismo job. También puedes crear varios jobs por entorno (p. ej. staging y producción) y usar labels para filtrar en dashboards y alertas.

¿Necesito Nginx para habilitar el status de PHP‑FPM?

No. El exporter habla FastCGI directamente con PHP‑FPM. Basta con habilitar pm.status_path y asegurarte de que FPM esté escuchando (TCP o socket). Nginx solo es útil si quieres exponer el status vía HTTP para humanos, lo cual no es necesario para Prometheus.

¿Qué métricas de PHP‑FPM son más útiles para alertas?

La cola de listen (phpfpm_listen_queue), procesos ocupados/ociosos (phpfpm_processes por estado), alcanzar la capacidad máxima y el up del target. Combínalas con latencia de la app y errores 5xx en tu proxy para tener contexto completo.

¿Quieres revisar tu stack de observabilidad en Docker?

Si necesitas configurar exporters de forma segura y estandarizada, o crear dashboards y alertas útiles para tu equipo, hablemos.

Hablar sobre observabilidad en Docker

Ver también