SonarQube: El Guardián de la Calidad del Código

SonarQube es una plataforma de análisis estático de código diseñada para inspeccionar la calidad y seguridad del software de forma automática. Dicho sin humo ni marketing: SonarQube lee tu código como un detective obsesivo y te señala errores, malas prácticas, vulnerabilidades y “deuda técnica” (ese conjunto de decisiones rápidas que luego pasan factura).

A través de reglas basadas en estándares de la industria, SonarQube evalúa aspectos como bugs potenciales, código duplicado, complejidad, cobertura de pruebas, vulnerabilidades de seguridad y mantenibilidad. El resultado no es solo una lista de fallos, sino una radiografía del estado real del proyecto, permitiendo mejorar el código de forma continua.

En entornos profesionales se integra dentro del ciclo de desarrollo (CI/CD), analizando automáticamente cada cambio en el código para evitar que los problemas crezcan en silencio. La filosofía es simple pero poderosa: la calidad no se inspecciona al final, se construye desde el principio.

En esta práctica utilizarás SonarQube para analizar un proyecto real, interpretar sus métricas y aplicar mejoras, entendiendo cómo la calidad del código impacta directamente en la seguridad, el rendimiento y la mantenibilidad del software. Porque el código funciona… hasta que deja de hacerlo, y ahí es donde empieza la ingeniería de verdad.

Arquitectura del proyecto

En la máquina Ubuntu tendrás:

  • SonarQube (contenedor): servidor web + motor de análisis.
  • PostgreSQL (contenedor): base de datos de SonarQube.
  • Contenedores de desarrollo: php-apache, tomcat, etc.
  • Código fuente en el HOST (carpeta del alumno/grupo) y montado en los contenedores de desarrollo.
  • Sonar Scanner (mejor en un contenedor aparte, o instalado en el host) que:
    • lee el código (desde el host o volumen compartido)
    • manda el análisis a SonarQube por HTTP.

Patrón recomendado:

  • El código vive en /home/alumno/proyectos/proyectoX
  • Ese directorio se monta en:
    • el contenedor de desarrollo (para ejecutar)
    • el contenedor “scanner” (para analizar)

FASE 1 — Montar SonarQube en Docker (Ubuntu)

Dejar SonarQube funcionando en la misma máquina Ubuntu, dentro de contenedores Docker, con base de datos PostgreSQL y persistencia, accesible desde el navegador.

Al terminar, podrás entrar a:

  • http://localhost:9000 (si estás en la misma máquina)
  • o http://IP_DE_LA_MAQUINA:9000 (si accedes desde otra)

1) Comprobar requisitos previos

1.1 Verifica que Docker funciona

En la terminal:

docker --version
docker ps

Si docker ps no da error, Docker está operativo.

1.2 Verifica que tienes Docker Compose

En Ubuntu moderno suele ser el plugin docker compose (con espacio):

docker compose version

Si te funciona, perfecto. Si no, lo instalaremos más adelante (pero normalmente ya viene si Docker está bien instalado).


2) Preparar carpeta del proyecto

Vamos a trabajar de forma ordenada en una carpeta específica para SonarQube.

mkdir -p ~/proyectos/sonarqube-docker
cd ~/proyectos/sonarqube-docker

Dentro crearemos el docker-compose.yml.


3) Ajuste del sistema: vm.max_map_count (IMPORTANTE)

SonarQube usa Elasticsearch internamente y en Linux necesita este parámetro del kernel.

3.1 Ver el valor actual

sysctl vm.max_map_count

Si te devuelve algo como 65530 o mas bajo, hay que subirlo.

3.2 Subirlo temporalmente (hasta reinicio)

sudo sysctl -w vm.max_map_count=262144

3.3 Hacerlo permanente

echo "vm.max_map_count=262144" | sudo tee /etc/sysctl.d/99-sonarqube.conf
sudo sysctl --system

✅ Comprobación final:

sysctl vm.max_map_count

Debe quedar en 262144.


4) Crear el archivo docker-compose.yml

En la carpeta ~/proyectos/sonarqube-docker crea el archivo:

nano docker-compose.yml

Pega esto:

services:
  db:
    image: postgres:15
    container_name: sonar-db
    environment:
      POSTGRES_USER: sonar
      POSTGRES_PASSWORD: sonar
      POSTGRES_DB: sonarqube
    volumes:
      - sonar_db_data:/var/lib/postgresql/data
    networks:
      - sonar-net
    restart: unless-stopped

  sonarqube:
    image: sonarqube:community
    container_name: sonarqube
    depends_on:
      - db
    ports:
      - "9000:9000"
    environment:
      SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonarqube
      SONAR_JDBC_USERNAME: sonar
      SONAR_JDBC_PASSWORD: sonar
    volumes:
      - sonar_data:/opt/sonarqube/data
      - sonar_extensions:/opt/sonarqube/extensions
      - sonar_logs:/opt/sonarqube/logs
    networks:
      - sonar-net
    restart: unless-stopped

volumes:
  sonar_db_data:
  sonar_data:
  sonar_extensions:
  sonar_logs:

networks:
  sonar-net:
    driver: bridge

Guarda y sal:

  • CTRL + O, Enter
  • CTRL + X

5) Arrancar SonarQube

En la misma carpeta:

docker compose up -d

Comprueba que están levantados:

docker ps

Deberías ver:

  • sonar-db
  • sonarqube

6) Ver logs y esperar a que esté listo

SonarQube tarda un poco en arrancar (no es instantáneo).

Para ver el estado:

docker logs -f sonarqube

Cuando veas un mensaje tipo “SonarQube is up” o que el sistema ya ha iniciado, ya puedes abrir el navegador.

(Para salir de logs: CTRL + C)


7) Acceso web y primer login

Abre en el navegador:

  • http://localhost:9000

Credenciales por defecto:

  • Usuario: admin
  • Contraseña: admin

Al entrar, SonarQube te obligará a cambiar la contraseña. Pon una segura (y anótala).



8) Problemas típicos (y solución rápida)

“SonarQube no arranca / se reinicia”

Mira logs:

docker logs --tail 200 sonarqube

Casi siempre es vm.max_map_count o falta de RAM.

“No puedo entrar a localhost:9000”

Verifica:

  • ¿está el contenedor levantado? docker ps
  • ¿otro servicio usa el puerto 9000? (raro, pero posible)

FASE 2 — Proyectos de ejemplo + preparación para análisis


1) Estructura de carpetas (base del universo)

Cada grupo trabajará con esta estructura:

mkdir -p ~/proyectos/grupo01/proyecto-php/src
mkdir -p ~/proyectos/grupo01/proyecto-java/src
cd ~/proyectos/grupo01

La regla cósmica:

El código vive en el HOST, y se monta en los contenedores.

Esto permite:

  • Ejecutar código en contenedor
  • Analizar el mismo código con Sonar

2) Proyecto PHP con Apache en contenedor

Entramos:

cd ~/proyectos/grupo01/proyecto-php

2.1 Crear archivo PHP con “malos olores”

nano src/index.php

Pega esto:

<?php

function suma($a, $b){
    return $a + $b;
}

function suma2($a, $b){ // duplicación
    return $a + $b;
}

$x = 5;
$y = 10;

if($x == $y){
    echo "Son iguales";
} else {
    echo "No son iguales";
}

echo "<br>Resultado: " . suma($x, $y);

// Código muerto
$z = 100;

?>

Guarda y sal.

Este archivo tiene:

  • Duplicación
  • Código muerto
  • Comparación débil
  • Poca mantenibilidad

Perfecto para SonarQube.


2.2 Crear docker-compose del proyecto PHP

nano docker-compose.yml
services:
  php-apache:
    image: php:8.2-apache
    container_name: php-grupo01
    ports:
      - "8081:80"
    volumes:
      - ./src:/var/www/html
    restart: unless-stopped

Arrancar:

docker compose up -d

Abrir navegador:

  • http://localhost:8081

Debe mostrar:

No son iguales
Resultado: 15

Si funciona, el contenedor ejecuta el código que vive en el host. Exactamente lo que queremos.


3) Crear configuración básica de Sonar para PHP

En la raíz del proyecto PHP:

nano sonar-project.properties
sonar.projectKey=lab1-php
sonar.projectName=Proyecto PHP Lab1
sonar.projectVersion=1.0
sonar.sources=src
sonar.sourceEncoding=UTF-8

Este archivo le dice al scanner:

  • qué proyecto es
  • dónde está el código
  • qué analizar

(No ejecutamos aún.)


4) (Opcional pero recomendado) Proyecto Java simple

Entramos:

cd ~/proyectos/grupo01/proyecto-java
nano src/Main.java
public class Main {

    public static int suma(int a, int b){
        return a + b;
    }

    public static int suma2(int a, int b){ // duplicación
        return a + b;
    }

    public static void main(String[] args){
        int x = 5;
        int y = 5;

        if(x == y){
            System.out.println("Iguales");
        }

        int z = 100; // código muerto
        System.out.println(suma(x, y));
    }
}

sonar-project.properties para Java

nano sonar-project.properties
sonar.projectKey=lab1-java
sonar.projectName=Proyecto JAVA Lab1
sonar.projectVersion=1.0
sonar.sources=.
sonar.sourceEncoding=UTF-8

(No hace falta contenedor para analizar Java simple.)


5) Concepto crítico que deben entender

SonarQube no analiza contenedores.

Analiza carpetas con código.

Por eso:

  • El código está en el host
  • El contenedor solo ejecuta
  • El scanner leerá la carpeta del host

Esto es exactamente cómo funciona en empresas reales.



FASE 3 — Primer análisis real con Sonar Scanner


1) Crear Token en SonarQube

El scanner necesita autenticarse. No se usan usuario/contraseña, se usa token.

Paso 1 — Entrar en SonarQube

Abrir:

http://localhost:9000 o http://ipservidor:9000

Login con tu usuario.


Paso 2 — Crear token

Ir a:

User → My Account → Security → Generate Token

Nombre sugerido:

scanner-grupo01

Copiar el token (solo se muestra una vez).

Guárdalo. Es la llave del reino.


2) Ejecutar Sonar Scanner desde contenedor

No instalamos nada en el host. Usamos un contenedor efímero. Limpio. Reproducible. Profesional.

Nos situamos en el proyecto PHP:

cd ~/proyectos/grupo01/proyecto-php

Ahora ejecutamos:

sudo docker run --rm --network host \
  -e SONAR_HOST_URL="http://127.0.0.1:9000" \
  -e SONAR_TOKEN="sqa_3a808da1a78a8cbefd19cc39638a829ccb69e4ed" \
  -v "$(pwd):/usr/src" \
  -w /usr/src \
  sonarsource/sonar-scanner-cli \
  -Dsonar.ws.timeout=120 \
  -Dsonar.scanner.ws.timeout=120

3) Qué está pasando realmente El contenedor scanner:

  • Entra
  • Lee /usr/src (tu proyecto montado)
  • Lee sonar-project.properties
  • Analiza el código
  • Envía resultados a SonarQube
  • Muere (porque usamos --rm)

Herramienta efímera. Análisis persistente.


4) Ver el resultado del análisis

Ir a:

http://ip_del_server:9000

Entrar en:

Projects

Debería aparecer:

Proyecto PHP Grupo01

Entrar y observar:

  • Bugs
  • Vulnerabilities
  • Code Smells
  • Maintainability Rating
  • Duplications

Tu código imperfecto ahora tiene diagnóstico.


5) Analizar también el proyecto Java

Entramos:

cd ~/proyectos/grupo01/proyecto-java

Lanzamos scanner igual:

sudo docker run --rm --network host \
  -e SONAR_HOST_URL="http://127.0.0.1:9000" \
  -e SONAR_TOKEN="sqa_3a808da1a78a8cbefd19cc39638a829ccb69e4ed" \
  -v "$(pwd):/usr/src" \
  -w /usr/src \
  sonarsource/sonar-scanner-cli \
  -Dsonar.ws.timeout=120 \
  -Dsonar.scanner.ws.timeout=120

Ir a SonarQube → Projects → ver Proyecto Java Grupo01.


6) Problemas típicos y cómo sobrevivir


“Not authorized”

Token mal puesto o copiado con espacios.

Regenera token y prueba otra vez.


“Project not found”

Falta sonar-project.properties o está mal.

Verifica que esté en la raíz del proyecto.


“SonarQube is not ready”

El servidor aún no terminó de arrancar.

Espera 30–60s y repite.


Importante

  • Sonar no ejecuta código → lo analiza estáticamente
  • Detecta:
    • Duplicación
    • Código muerto
    • Riesgos de seguridad
    • Mala mantenibilidad
  • El análisis queda guardado aunque el scanner desaparezca
  • Esto es exactamente lo que hacen empresas reales en CI/CD

Magnífica jugada pedagógica. Aquí el alumno deja de jugar con ejemplos de juguete y entra en territorio real: código con historia, decisiones, cicatrices y pecado técnico acumulado. Eso es donde SonarQube brilla de verdad. Vamos a plantearlo como RETO FINAL — Análisis real de un proyecto propio listo para entregar a alumnos.


🧪 RETO FINAL — Auditoría real con SonarQube

Misión

Vas a analizar con SonarQube un proyecto real desarrollado por ti, no un ejemplo:

Puedes elegir UNO o Todos:

  • Tu CRUD Java/PHP del proyecto anterior
  • Un WordPress (tema propio, plugin o código modificado)
  • Cualquier proyecto mediano (mínimo ~20–30 archivos)

Objetivo: tratar el proyecto como si fueras el equipo de calidad de una empresa real.


Qué debes conseguir

  1. Analizar el proyecto completo con SonarQube
  2. Evaluar el estado real del código
  3. Detectar problemas técnicos reales
  4. Aplicar refactorización
  5. Mejorar el Quality Gate

Fase 1 — Preparar el proyecto

Regla clave

SonarQube analiza código fuente, no contenedores ni binarios.

Tu proyecto debe tener:

  • Carpeta raíz clara
  • Código fuente accesible
  • Sin vendor/, node_modules/, target/, etc. (opcional pero recomendado ignorarlos)

Crear sonar-project.properties

En la raíz del proyecto:

Para PHP / WordPress

sonar.projectKey=proyecto-real-php
sonar.projectName=Proyecto Real PHP
sonar.sources=.
sonar.sourceEncoding=UTF-8

Para Java

sonar.projectKey=proyecto-real-java
sonar.projectName=Proyecto Real Java
sonar.sources=src
sonar.sourceEncoding=UTF-8

Fase 2 — Ejecutar análisis

Desde la raíz del proyecto:

sudo docker run --rm --network host \
  -e SONAR_HOST_URL="http://127.0.0.1:9000" \
  -e SONAR_TOKEN="TU_TOKEN" \
  -v "$(pwd):/usr/src" \
  -w /usr/src \
  sonarsource/sonar-scanner-cli \
  -Dsonar.ws.timeout=120

Ir a SonarQube → Projects → entrar al proyecto.


Fase 3 — Diagnóstico técnico

Debes analizar:

1. Bugs

Errores potenciales de ejecución.

2. Vulnerabilities

Riesgos de seguridad (inyección, validación, etc.)

3. Code Smells

Problemas de diseño/mantenibilidad.

4. Duplicación

Código repetido.

5. Complejidad

Métodos demasiado complejos.


Fase 4 — Informe técnico (parte importante del reto)

Debes escribir un informe con:

Estado inicial

  • Quality Gate: PASS / FAIL
  • Nº Bugs
  • Nº Vulnerabilities
  • Nº Code Smells
  • Maintainability Rating

Análisis crítico

Selecciona mínimo 5 problemas reales y explica:

  • Qué problema detectó SonarQube
  • Por qué es un problema técnico real
  • Qué riesgo tiene (mantenibilidad, seguridad, errores)
  • Cómo lo solucionaste

Refactorización aplicada

Ejemplos:

  • Eliminación de duplicación
  • Validación de entrada
  • Mejora de legibilidad
  • División de funciones largas
  • Tipado fuerte
  • Eliminación de código muerto

Estado final

  • Nuevo Quality Gate
  • Cambios en métricas
  • Mejora del rating

Bonus

  • Integrar análisis en GitHub Actions / GitLab CI
  • Hacer que el merge falle si el gate está en rojo
  • Añadir tests → mejorar coverage
  • Analizar plugin o tema WordPress completo
  • Comparar análisis antes/después


Cambiar SonarQube a español

Método 1 — Cambiar idioma del usuario (lo primero que debes probar)

  1. Entra en SonarQube → http://localhost:9000
  2. Arriba a la derecha → My Account
  3. Preferences
  4. Language → Spanish (Español)
  5. Guardar

Si tu versión tiene traducción cargada, la interfaz cambia inmediatamente (menús, labels, etc.).


Si NO aparece Español en la lista

Entonces tu SonarQube no tiene el paquete de idioma instalado (pasa en algunas builds).

Método 2 — Instalar plugin de idioma (si disponible)

  1. Administration → Marketplace
  2. Buscar: Spanish o Localization
  3. Si aparece plugin de idioma → Install
  4. Reiniciar SonarQube

⚠️ En versiones recientes de SonarQube Community, el marketplace ya no siempre incluye todos los idiomas, y parte de la interfaz puede quedarse en inglés aunque cambies idioma. No es fallo, es así por diseño.


Realidad técnica

  • El análisis, reglas, métricas → no dependen del idioma
  • Muchos equipos trabajan SonarQube en inglés (terminología estándar industria)
  • Aunque pongas español, algunas secciones seguirán en inglés
  • Los nombres clave no se traducen:
    • Quality Gate
    • Code Smell
    • Vulnerability
    • Maintainability

Esto es normal.