Expor métricas PHP‑FPM para Prometheus com exporter em Docker Compose (tutorial)

Docker & Containers · Por · Publicado em · 7 min de leitura

Close-up de folha verde mostrando nervuras paralelas e textura
Fundo limpo e neutro, ideal para destaque de tutorial técnico Foto: hankaverzichova / Pixabay

Tutorial: expor métricas PHP‑FPM para Prometheus usando exporter em Docker Compose. Você vai habilitar o status do PHP‑FPM, subir um exporter dedicado e configurar o Prometheus para coletar as métricas. No fim, validamos com curl e na UI do Prometheus, além de dicas para múltiplos pools e segurança.

Arquitetura: como o scraping funciona

O PHP‑FPM expõe estatísticas no pm.status_path. Um exporter traduz esses dados para o formato do Prometheus e publica em /metrics. O Prometheus, então, faz o scrape desse endpoint periodicamente. Tudo roda em containers separados via Docker Compose.

Essa separação facilita isolar responsabilidades, aplicar limites e evoluir cada componente sem acoplamento. Veja os papéis e portas padrão:

Componente Porta Papel
php-fpm 9000/TCP Executa o pool PHP e expõe /status via FastCGI
php-fpm-exporter 9253/TCP Conecta no /status e serve /metrics
prometheus 9090/TCP Faz o scrape do exporter e armazena séries temporais

Pré-requisitos e avisos importantes

Antes de começar, você precisa de Docker e Docker Compose instalados e acesso ao terminal. Este passo a passo usa imagens oficiais e configurações mínimas para funcionar em desenvolvimento ou laboratório.

- Atenção: o status do PHP‑FPM não tem autenticação. Mantenha o acesso restrito à rede interna do Docker ou localhost. Não publique /status na internet.

- Atenção: mapear portas públicas expõe serviços. Prefira binding em 127.0.0.1 durante testes.

  • Docker e Docker Compose instalados
  • Permissão para rodar docker compose
  • Portas 9090 e 9253 livres na máquina local (ou ajuste)
  • Conhecimento básico de YAML e Linux

Estrutura de pastas do projeto

Criaremos duas pastas para separar a configuração do PHP‑FPM e do Prometheus. Os arquivos serão preenchidos nas próximas seções.

Estrutura 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 o status do PHP‑FPM (pm.status_path)

O exporter depende do endpoint de status do PHP‑FPM. Ative o pm.status_path e garanta que o PHP‑FPM escute em TCP (porta 9000) para facilitar a comunicação entre containers.

Salve o arquivo abaixo 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 e php-fpm-exporter

Agora vamos orquestrar o PHP‑FPM e o exporter. O exporter hipages/php-fpm_exporter conecta no /status via FastCGI e serve métricas HTTP na porta 9253.

Observação: o binding das portas pode ser alterado para 127.0.0.1:PORTA se você quiser restringir o acesso apenas ao 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 do exporter

Com o exporter servindo /metrics, configure o Prometheus para coletar periodicamente. Usaremos um job dedicado com target apontando para o serviço do exporter no Compose.

Salve o arquivo abaixo como prometheus/prometheus.yml e adicione o serviço prometheus ao Compose.

global:
  scrape_interval: 15s

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

Subir os containers e validar as métricas

Hora de subir tudo e conferir. Vamos criar/atualizar o docker-compose.yml com o Prometheus, iniciar os serviços e verificar se o /metrics retorna dados. Também vale checar os targets na UI do Prometheus.

Dica: se quiser dashboards, veja o guia de Prometheus+Grafana em Docker Compose em como configurar Prometheus e 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".

Boas práticas, múltiplos pools e próximos passos

Para cada instância/pool de PHP‑FPM, o padrão mais simples é executar um exporter por target e adicionar todos no Prometheus (vários targets no mesmo job). Evite expor /status publicamente: deixe a comunicação restrita à rede interna do Docker.

Algumas recomendações práticas:

  • Restrinja ports: mapeie para 127.0.0.1:9253 e 127.0.0.1:9090 quando possível.
  • Mantenha pm.status_path habilitado só onde o exporter acessa. Em produção, não publique via HTTP externo.
  • Use labels coerentes (instance, service, env) no Prometheus para facilitar dashboards.
  • Crie alertas para fila de listen alta e processos ocupados persistentes.
  • Otimize pm.* do FPM conforme carga; métricas ajudam a validar tuning. Veja vazamento de memória no PHP‑FPM.
  • Para visualizar, conecte o Prometheus ao Grafana. Compare stacks em Prometheus+Grafana vs Loki+Tempo e complemente com logs centralizados (Fluentd + Elasticsearch).

Erros comuns e como diagnosticar rapidamente

Alguns problemas aparecem com frequência durante a configuração inicial. Confira as causas típicas e correções diretas a seguir.

  • Conexão recusada no exporter: confirme se o php-fpm está ouvindo em 9000 e o nome do serviço (tcp://php-fpm:9000/status).
  • 404 no /status: verifique pm.status_path no www.conf e reinicie o FPM (recrie o container).
  • Exporter UP, mas métricas vazias: confira permissões e se o pool ativo é o [www].
  • Target DOWN no Prometheus: teste curl no host do Prometheus; se resolver com 127.0.0.1 binding, ajuste a rede/ports.
  • Alto listen_queue constante: é sinal de saturação; ajuste pm.max_children e investigue gargalos de CPU/IO.

Perguntas frequentes

Posso usar socket UNIX em vez de TCP para o PHP‑FPM?

Sim. O exporter consegue falar FastCGI via socket. Aponte --phpfpm.scrape-uri para o caminho do socket, por exemplo unix:///usr/local/var/run/php-fpm.sock, e monte o socket no container do exporter. Em Compose, use volumes compartilhados entre php-fpm e o exporter.

É seguro expor o /metrics do exporter na internet?

Evite. Exponha o /metrics somente internamente (rede do Docker ou 127.0.0.1) e deixe o Prometheus coletar localmente. Se precisar acesso remoto, coloque autenticação e restrições de IP em um proxy na frente do exporter ou acesse via VPN.

Como monitorar vários pools ou serviços PHP‑FPM?

Execute um exporter por instância/pool e adicione todos como targets no Prometheus no mesmo job. Você também pode rodar múltiplos jobs por ambiente (ex.: staging e produção) e usar labels para filtrar em dashboards e alertas.

Preciso do Nginx para habilitar o status do PHP‑FPM?

Não. O exporter fala FastCGI diretamente com o PHP‑FPM. Basta habilitar pm.status_path e garantir que o FPM esteja escutando (TCP ou socket). Nginx é útil apenas se você quiser expor o status via HTTP para humanos, o que não é necessário ao Prometheus.

Quais métricas do PHP‑FPM são mais úteis para alertas?

A fila de listen (phpfpm_listen_queue), processos ocupados/ociosos (phpfpm_processes por estado), capacidade máxima atingida, e o up do target. Combine com latência de app e erros 5xx em seu proxy para ter contexto mais completo.

Quer revisar sua stack de observabilidade em Docker?

Se você precisa configurar exporters de forma segura e padronizada, ou criar dashboards e alertas úteis para seu time, vamos conversar.

Falar sobre observabilidade em Docker

Veja também