Qualidade e segurança no código são pontos fundamentais quando falamos em desenvolvimento e engenharia de software, e monitorar esses pontos durante as etapas de um projeto requerem atenção, pois ajudam a reduzir riscos operacionais e de segurança, além de ajudar a facilitar a manutenção e obter um retorno positivo em questão de confiabilidade do ativo de software quando dada a devida atenção nos apontamentos de códigos.
Uma forma de obter esses valores de qualidade e segurança são através de métricas, que normalmente são números gerados por um sistema com base em comportamentos e atividades que ocorrem durante a operação de um software/ambiente. Portanto, com as métricas é possível medir índices relevantes, quantificar e qualificar aspectos do software, contribuindo durante todo o processo de desenvolvimento de software e melhoria contínua.
Este artigo visa mostrar o processo de integração do SonarQube com Prometheus e Grafana, mostrando a implementação de uma solução capaz de gerar métricas, coletar as métricas e demonstrá-las em gráficos de maneira mais amigável e interpretativa.
Pré-requisitos para o ambiente
Esta seção é responsável por apresentar os pré-requisitos principais para que esta solução funcione e esteja apta a ser operada.
Ferramentas necessárias
- Docker instalado.
docker --version
- Docker Compose instalado (nas versões mais atuais do Docker o Compose já vem incluso).
docker compose version
- Token do Vault e contexto configurados no terminal.
export VAULT_API_KEY="token vault gerado" # Token gerado no Vault
export VAULT_CONTEXT="operation/sonarqube" # Necessário para o Prometheus/Sonarqube
- Usuário exclusivo do Prometheus cadastrado na base do SonarQube para acesso ao endpoint de métricas, e, token cadastrado para este usuário.
- Token do usuário do Prometheus armazenado no Vault (key).
Arquitetura e funcionamento do ambiente da solução
Como esta solução é baseada em containers, foi adotado o Docker Compose para facilitar a execução deles com suas respectivas configurações particulares e também para facilitar o preparo do ambiente incluindo redes e volumes para cada um dos containers.
Arquitetura para o SonarQube
O SonarQube, até o momento, não dispõe de um plugin nativo que expõe métricas em um endpoint, sendo assim, para essa solução, foi utilizado um exporter desenvolvido pela comunidade que possibilita gerar e disponibilizar as métricas de contexto do SonarQube em um endpoint.
O exporter utilizado trata-se de um arquivo .jar na qual é copiado no diretório extensions/plugins dentro do container do SonarQube, e para facilitar este processo, conforme o Código 1, foi elaborado uma imagem do SonarQube que copia toda a estrutura do diretório extensions/ (linha 11) na qual inclui o arquivo Java, além de configurar permissão de execução do binário (linha 12).
1 FROM sonarqube:latest
2
3 # Instalar dependências para comunicação com o Vault
4 RUN apt-get update && \
5 apt-get install -y curl jq gosu && \
6 apt-get clean && rm -rf /var/lib/apt/lists/*
7
8 # Copia a pasta extensions preservando a estrutura dela
9 # incluindo o plugin/exporter para fornecer métricas ao
10 # Prometheus presente em extensions/plugins
11 COPY extensions /sonarqube/extensions
12 RUN chmod +x "/sonarqube/extensions/plugins/sonar-prometheus-exporter-1.0.0-SNAPSHOT.jar"
13
14 # Copia o wrapper e define permissões
15 COPY entrypoint.sh /entrypoint.sh
16 RUN chmod +x /entrypoint.sh
17
18 # Usa o entrypoint original via wrapper
19 ENTRYPOINT ["/entrypoint.sh"]
Esse foi O Código 1 – Arquivo Dockerfile para gerar imagem do SonarQube.
O endpoint de métricas do SonarQube estará disponível para acesso mediante usuário e senha, ou token, cadastrados na base do SonarQube (conforme a Figura 1), ou seja, em uma tentativa de acesso sem autenticação estabelecida é retornado o erro 401. Portanto, para esta solução, no SonarQube, foi cadastrado o usuário prometheus e gerado para ele um token para obter essa autorização.

O serviço do SonarQube configurado no arquivo Docker Compose, como mostrado abaixo no Código 2, foi incluído na rede de monitoramento monitoramento (linha 25) a fim do serviço SonarQube ter comunicação com os outros serviços de monitoramento da solução, e, para isso, essa rede de monitoramento foi configurada na seção de networks do Compose como uma rede já existente/externa a este Compose (linhas 57 e 58).
1 services:
2 sonarqube:
3 build:
4 context: .
5 dockerfile: Dockerfile
6 image: sonarqube-secure:latest
7 entrypoint: ["/entrypoint.sh"]
8 command: ["/sonarqube/docker/entrypoint.sh"]
9 container_name: sonarqube
10 depends_on:
11 postgres:
12 condition: service_healthy
13 restart: unless-stopped
14 ports:
15 - "9000:9000"
16 environment:
17 VAULT_API_KEY: "${VAULT_API_KEY}"
18 VAULT_CONTEXT: "${VAULT_CONTEXT}"
19 TARGET_UID: "1000"
20 TARGET_GID: "0"
21 volumes:
22 - sonarqube_data:/sonarqube/data
23 networks:
24 - sonarnet
25 - monitoramento
26
27
28 postgres:
29 build:
30 context: ./postgres
31 dockerfile: Dockerfile
32 image: postgres-secure:latest
33 entrypoint: ["/postgres-entrypoint.sh"]
34 command: ["postgres"]
35 container_name: sonarqube_postgres
36 restart: unless-stopped
37 environment:
38 VAULT_API_KEY: "${VAULT_API_KEY}"
39 VAULT_CONTEXT: "${VAULT_CONTEXT}"
40 volumes:
41 - postgres_data:/var/lib/postgresql/data
42 networks:
43 - sonarnet
44 healthcheck:
45 test: ["CMD", "pg_isready", "-U", "sonar"]
46 interval: 10s
47 timeout: 5s
48 retries: 5
49
50 volumes:
51 sonarqube_data:
52 postgres_data:
53
54 networks:
55 sonarnet:
56 driver: bridge
57 monitoramento:
58 external: true #depende da rede monitoramento
Esse foi o Código 2 – Arquivo docker-compose.yml para o ambiente do SonarQube
Arquitetura para o Prometheus e Grafana
O processo de customização de uma imagem para o Prometheus foi necessário devido ao fato da imagem oficial dele ser minimalista a ponto de não possuir gerenciador de pacotes para instalação de recursos necessários dentro do próprio container para interação e retorno do token armazenado no Vault.
Para que o token do usuário prometheus não seja importado como hard code no projeto, conforme o Código 3, foi necessária a implementação de um script entrypoint.sh no Dockerfile.prometheus para a execução do ambiente puxando o valor da key PROMETHEUS_TOKEN do Vault de forma segura para o arquivo de regras do Prometheus (linha 27 a 31).
1 #!/bin/sh
2 set -e
3
4 # Especificação do domínio
5 VAULT_DOMAIN="domain.com.br"
6
7# 🔒 Verificação de variáveis do Vault
8 [ -z "$VAULT_API_KEY" ] && echo "❌ VAULT_API_KEY não definido" && exit 1
9 [ -z "$VAULT_CONTEXT" ] && echo "❌ VAULT_CONTEXT não definido" && exit 1
10
11 VAULT_URL="https://${VAULT_DOMAIN}/v1/${VAULT_CONTEXT}"
12 echo "🔐 Buscando variáveis do Vault em $VAULT_URL"
13
14 RESPONSE=$(curl -sSf -H "X-Vault-Token: ${VAULT_API_KEY}" "$VAULT_URL")
15
16 # Gera arquivo temporário com export seguro
17 echo "$RESPONSE" | jq -r '.data | to_entries[] | "export \(.key)=\"\(.value)\""' > /tmp/.env.runtime
18
19 # Carrega variáveis no ambiente
20 set -a
21 . /tmp/.env.runtime
22 set +a
23
24 rm -f /tmp/.env.runtime
25
26 # Configura token Sonar se existir
27 if [ -n "$PROMETHEUS_TOKEN" ]; then
28 echo "📄 Configurando arquivo sonar..."
29 echo "$PROMETHEUS_TOKEN" > /etc/prometheus/sonar
30 chown prometheus-user:prometheus-group /etc/prometheus/sona
31 fi
32
33 echo "✅ Variáveis injetadas do Vault"
34 echo "🚀 Iniciando Prometheus..."
35
36 # Executa Prometheus como prometheus-user 37 exec su-exec prometheus-user:prometheus-group prometheus "$@"
Este foi Código 3 – Arquivo entrypoint.sh para obter o token no Vault.
O valor extraído da key PROMETHEUS_TOKEN do Vault por meio do entrypoint.sh é configurada no container dentro do arquivo sonar no diretório /etc/prometheus, pois, conforme o Código mostrado, nas configurações de regras do Prometheus ela é passada como token file (linha 17) para acesso ao endpoint de métricas do SonarQube /api/prometheus/metrics (linha 14), com target especificado para o serviço sonarqube (linha 16) derivado do Compose do ambiente do SonarQube. 1
1 global:
2 scrape_interval: 15s
3 evaluation_interval: 15s
4
5 alerting:
6 alertmanagers:
7 - static_configs:
8 - targets: []
9
10 rule_files: []
11
12 scrape_configs:
13 - job_name: 'sonarqube'
14 metrics_path: '/api/prometheus/metrics'
15 static_configs:
16 - targets: ['sonarqube:9000']
17 bearer_token_file: '/etc/prometheus/sonar'
Esse foi o Código 4 – Configurando o serviço do SonarQube nas regras do arquivo Prometheus.
A imagem customizada gerada com o Dockerfile.prometheus, apresentada abaixo no Código 5, utiliza a técnica de multi-stage build (linhas 1 a 12) onde na primeira fase são instalados os recursos necessários e o Prometheus, e na segunda fase (linhas 16 a 41) é feita de fato a cópia do binário do Prometheus e a configuração da imagem final onde é criado um usuário exclusivo para execução do Prometheus bem como as configurações de permissões e execução do entrypoint.sh. Além disso, em específico, na linha 32 é configurado o usuário prometheus-user como proprietário do diretório /prometheus/data no container que também é refletido como proprietário no host devido ao mapeamento efetuado para este diretório com o Docker Compose (Código 7, linha 10).
1 #### Dockerfile seguro para Prometheus + Vault
2 FROM alpine:3.22.1 AS builder
3
4 WORKDIR /tmp
5
6 # Instala ferramentas necessárias apenas para build
7 RUN apk add --no-cache curl tar
8
9 # Baixa e extrai Prometheus (arquitetura amd64 recomendada)
10 RUN curl -sSL https://github.com/prometheus/prometheus/releases/download/v3.6.0/prometheus-3.6.0.linux-amd64.tar.gz \
11 | tar -xz && \
12 mv prometheus-3.6.0.linux-amd64/prometheus /tmp/prometheus
13
14 # ---------------------------------------------------------------
15
16 FROM alpine:3.22.1
17
18 # Cria usuário não-root
19 RUN addgroup -S prometheus-group && adduser -S prometheus-user -G prometheus-group
20
21 WORKDIR /prometheus
22
23 # Instala apenas dependências necessárias no runtime
24 RUN apk add --no-cache su-exec jq curl
25
26 # Copia binário Prometheus do builder
27 COPY --from=builder /tmp/prometheus /usr/local/bin/prometheus
28
29 # Diretórios de configuração e dados
30 RUN mkdir -p /etc/prometheus && \
31 mkdir -p /prometheus/data && \
32 chown -R prometheus-user:prometheus-group /prometheus /etc/prometheus
33
34 # Copia entrypoint e aplica boas práticas
35 COPY entrypoint.sh /prometheus/entrypoint.sh
36 RUN sed -i 's/\r$//' /prometheus/entrypoint.sh && \
37 chmod 755 /prometheus/entrypoint.sh && \
38 chown prometheus-user:prometheus-group /prometheus/entrypoint.sh
39
40 ENTRYPOINT ["/prometheus/entrypoint.sh"]
41 CMD ["--config.file=/etc/prometheus/prometheus.yml", "--storage.tsdb.path=/prometheus/data"]
Esse foi o Código 5 – Dockerfile para gerar a imagem do Prometheus com interação com o Vault..
Ao passo que foi gerado o arquivo Dockerfile.prometheus, foi também gerado o arquivo Dockerfile.grafana (Código 6) para customização da imagem do Grafana, adaptando as permissões e o usuário na qual irá executar o Grafana dentro do container. Além disso, a customização da imagem do Grafana também se justifica pelo processo de padronização das configurações do Docker Compose para a execução dos serviços (modo build).
1 FROM grafana/grafana:11.2.0
2
3 # Garante que /var/lib/grafana e /etc/grafana tenham UID/GID corretos
4 RUN mkdir -p /var/lib/grafana/plugins /etc/grafana && \
5 chown -R 472:472 /var/lib/grafana /etc/grafana
6
7 # Retorna para usuário grafana (472) 8 USER 472
Esse foi o Código 6 – Dockerfile para gerar a imagem do Grafa
No Código 7 é exibido o arquivo docker-compose.yml onde é configurada a execução do ambiente de monitoramento. Para a comunicação do Prometheus com o Vault, foi inserido as variáveis de ambiente VAULT_API_KEY e VAULT_CONTEXT (linhas 14 e 15). Além disso, também foi necessário estabelecer um nome fixo (linhas 38) para a rede de monitoramento em que o Prometheus e o Grafana fazem parte para facilitar o ingresso do serviço do SonarQube que é executado a partir de outro arquivo Docker Compose (Código 2). 1 services:
1 services:
2 prometheus:
3 build:
4 context: .
5 dockerfile: Dockerfile.prometheus
6 image: prometheus-secure:latest
7 container_name: prometheus
8 volumes:
9 - /monitoramento/prometheus/opt/prometheus.yml:/etc/prometheus/prometheus.yml:ro
10 - /monitoramento/prometheus:/prometheus/data:rw
11 ports:
12 - "19090:9090"
13 environment:
14 VAULT_API_KEY: "${VAULT_API_KEY}"
15 VAULT_CONTEXT: "${VAULT_CONTEXT}"
16 restart: unless-stopped
17 networks:
18 - monitor-net
19
20 grafana:
21 build:
22 context: .
23 dockerfile: Dockerfile.grafana
24 image: grafana-secure:latest
25 container_name: grafana
26 user: "472:472"
27 volumes:
28 - /monitoramento/grafana:/var/lib/grafana:rw
29 - /monitoramento/grafana/etc:/etc/grafana:rw
30 ports:
31 - "13000:3000"
32 restart: unless-stopped
33 networks:
34 - monitor-net
35
36 networks:
37 monitor-net:
38 name: monitoramento
39 driver: bridge
Esse foi o Código 7 – Docker Compose para preparar e executar o ambiente de monitoramento.
Diagrama da Arquitetura
Na Figura 2 é demonstrado, de forma simples, o diagrama da arquitetura desta solução visando facilitar o entendimento de forma visual, onde é mostrado os três containers (SonarQube, Prometheus e Grafana) fazendo parte da mesma rede para terem comunicação (monitoramento).
Além disso, no diagrama também é demonstrada a interação entre cada componente da solução, onde o Exporter inserido no container SonarQube fornece um endpoint de métricas, e o Prometheus, além de coletar essas métricas neste endpoint, se comunica com o Vault recebendo o token para ser configurado nas regras.
Por fim, é apresentado o Grafana que realiza a consulta de métricas armazenadas pelo Prometheus para gerar os dashboards.

Execução do ambiente
Para a execução do ambiente, tanto o ambiente de monitoramento quanto o ambiente do SonarQube, é necessário informar no terminal o token e contexto do Vault, conforme informado na seção de pré-requisitos deste documento.
Após informado o token e contexto do Vault, é preciso primeiro ter o ambiente de monitoramento em execução, pois é nele que é criada a rede na qual o SonarQube irá integrar-se posteriormente.
Abaixo está o comando para iniciar os containers e preparar o ambiente. Primeiro, execute o comando no diretório do ambiente de monitoramento. Em seguida, utilize este mesmo comando para executar no diretório correspondente ao ambiente do SonarQube.
docker compose up -d # Inicia os containers
Obs: Quando há alterações em arquivos externos ao docker-compose.yml como por exemplo, Dockerfiles, códigos ou arquivos que estão relacionados ao Dockerfile, se faz necessário executar o comando com a flag --build para forçar o build das imagens, assim, considerando o que foi alterado fora do docker-compose.yml. Exemplo:
docker compose up -d --build # Inicia os containers com build das imagens
Configuração do Grafana
Com a solução toda em execução, para configurar o Grafana, basta fazer a configuração da fonte de dados com o Prometheus indicando o hostname e porta do service do Prometheus (server URL em Connection) e salvar a conexão, conforme demonstrado na Figura 3 abaixo. Além disso, na Figura 3 é destacado na URL da página o UID desta conexão de fonte de dados, e esta informação será útil na importação de um dashboard pronto a seguir.

Após a configuração da fonte de dados, no Grafana, é possível construir os dashboards a partir das métricas coletadas e disponíveis na fonte de dados, porém, para este ambiente, e, demonstrado na Figura 4, foi utilizado a importação via modelo JSON de um dashboard pré-configurado disponibilizado pela comunidade, podendo ser configurado no Grafana em painéis de controle bastando alterar todas as ocorrências de uid do datasource do arquivo JSON com o uid da fonte de dados correspondente, conforme exemplo em destaque na Figura 3

Validação e funcionamento
Nesta seção será mostrado o ambiente em funcionamento no host em que ele está presente e também na interface web na qual os serviços podem ser acessados e visualizados pelo navegador.
Validando no servidor
No host onde o Docker está operacional, utilize o seguinte comando para mostrar os containers em execução, sendo que, este mesmo comando deve ser informado no terminal estando nos diretórios correspondentes de cada ambiente (monitoramento e SonarQube).
docker compose ps # Exibe os containers de cada projeto Compose
Na Figura 5 são mostrados em execução os containers que compõem o monitoramento, grafana e prometheus.

Na Figura 6 é exibido o container do sonarqube em execução, juntamente com o container do Postgres na qual o SonarQube precisa para se manter.

Verificando as configurações do container sonarqube, conforme a Figura 7, nota-se que ele está fazendo parte da rede de monitoramento, possibilitando assim a comunicação entre ele e o Prometheus.

É possível encontrar os três containers fazendo parte da mesma rede inspecionando esta rede de monitoramento, conforme demonstrado na Figura 8.

Validando no navegador
Abaixo, na Figura 9, é demonstrado o Exporter do Prometheus presente na interface administração do SonarQube, havendo também, por uma ventura necessidade, a possibilidade de ativar ou desativar métricas nas quais este Exporter prove para o Prometheus coletar.

Todas essas métricas que o Exporter disponibiliza são do tipo gauge, ou seja, sofrem incremento ou decremento ao longo das análises do projeto. Sendo assim, as possíveis métricas que este Exporter disponibiliza são:
1. sonarqube_complexity: Complexidade ciclomática;
2. sonarqube_security_hotspots: Pontos críticos de segurança;
3. sonarqube_sqale_index: Esforço total (em minutos) para corrigir todos os problemas do componente e atender aos requisitos;
4. sonarqube_duplicated_lines: Linhas duplicadas;
5. sonarqube_ncloc: Linhas de código sem comentários;
6. sonarqube_bugs: Erros (bugs);
7. sonarqube_vulnerabilities: Vulnerabilidades;
8. sonarqube_lines: Linhas totais;
9. sonarqube_violations: Problemas;
10. sonarqube_code_smells: Indícios de má qualidade;
11. sonarqube_alert_status: Status do projeto em relação ao seu limite de qualidade (quality gate);
12. sonarqube_coverage: Cobertura por testes;
13. sonarqube_lines_to_cover: Linhas que devem ser cobertas por testes.
Na configuração deste Exporter, ele por padrão indica o endpoint de métricas como sendo o …/api/prometheus/metrics, portanto, assim como feito na configuração do arquivo de regras do Prometheus, este mesmo caminho foi mantido como padrão. Na Figura 10 é mostrado este endpoint na qual o Prometheus acessa para coletar as métricas.

Abaixo, na Figura 11, é exibido a tela do Prometheus na qual contém os targets que foram configurados para ele puxar as métricas, onde, nota-se o target do SonarQube com o service, endpoint e labels especificadas.

No Grafana, após feita a configuração de fonte de dados com o Prometheus, é possível configurar dashboards com gráficos e visualizações baseados nas métricas coletadas pelo Prometheus. Abaixo, na Figura 12, é demonstrado um exemplo de dashboard configurado com as métricas coletadas pelo Prometheus.

Resultados
Neste estágio inicial, os ambientes de monitoramento e o de análise de qualidade de código foram devidamente configurados e estão operando conforme o esperado. Embora os indicadores e métricas ainda estejam em processo de alimentação, é possível visualizar os painéis e compreender a estrutura que permitirá, futuramente, realizar uma análise mais detalhada da evolução do projeto.
A integração com o SonarQube e o Grafana estabelece uma base sólida para o acompanhamento contínuo da qualidade e segurança do código, viabilizando decisões técnicas futuras baseadas no cenário real em que o projeto é desenvolvido e nas métricas, conforme forem sendo consolidadas nos gráficos.
Com os dados do SonarQube consolidados em gráficos, ao longo do tempo, é possível analisar a evolução de indicadores, como complexidade, densidade de comentários, duplicação de códigos, entre outros. Esses dados facilitam a identificação de tendências, gargalos, e aspectos que demandam atenção, e com isso facilitam a tomada de decisão para melhorias nos processos de qualidade e segurança de código, alinhados às boas práticas.
Conclusão
Com a solução implantada, o ambiente está apto a receber dados/métricas para alimentar os gráficos referente às análises do SonarQube, e com isso, impactar positivamente com o monitoramento contínuo.
Com a possibilidade de monitorar e acompanhar os indicadores do sistema, o processo de melhoria contínua é reforçado por decisões mais assertivas, baseadas em dados reais e atualizados constantemente.
Portanto, esta integração do SonarQube com o Prometheus e Grafana não trata-se apenas de uma questão técnica, mas sim de um passo estratégico em direção à qualidade, segurança e confiabilidade.
Referências
● Docker Networking: https://docs.docker.com/engine/network/
● Networking in Compose: https://docs.docker.com/compose/how-tos/networking/
● Sonar metrics exporter: https://github.com/DomGiorda/sonar-metrics-exporter
● Prometheus Configuration: https://prometheus.io/docs/prometheus/latest/configuration/configuration/
● Build your first dashboard: https://grafana.com/docs/grafana/latest/getting-started/build-first-dashboard/?pg=dashboards&plcmt=hero-btn2
● Understanding measures and metrics: https://docs.sonarsource.com/sonarqube-server/user-guide/code-metrics/metrics-definition




