Para el vídeo de esta semana quería mostrarte una de las herramientas que más he visto en diferentes compañías para el análisis de código estático, que es SonarQube.
Para que probar el misma no te suponga ningún coste, y que no dependas de SonarCloud y que los proyectos queden públicos, me he buscado la forma de hospedarlo dentro de un dev container para que puedas probarlo con la versión Community Edition en local, y luego lo despliego en Codespaces por si quieres probar a integrarlo con tus plataformas de CI/CD como GitHub o Azure DevOps. En este artículo te comparto el detalle de cómo lo he hecho.
Configuración del dev container
Para poder configurar el dev container en este escenario vas a necesitar tener en cuenta tres archivos:
- El docker-compose que te permitirá no solo configurar el servidor de SonarQube sino además el contenido de tu workspace (donde está tu código y tus cosas vaya)
- El Dockerfile que utilizaré para instalar la herramienta sonnar-scanner que es la que hace el trabajo para luego mandarlo al servidor de SonarQube.
- El devcontainer.json es el archivo que hace que el devcontainer funcione y que hace de punto de entrada a lo anterior.
El docker-compose.yaml
Como te decía, en este lo que voy a definir son los tres servicios que necesito en este escenario:
# Sonarqube Community Edition running on Docker
# https://hub.docker.com/_/sonarqube/
# https://docs.sonarqube.org/latest/setup/get-started-2-minutes/
version: '3.8'
services:
app:
container_name: dev
build:
context: .
dockerfile: Dockerfile
volumes:
- ../..:/workspaces:cached
# Overrides default command so things don't shut down after the process ends.
command: sleep infinity
# Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function.
network_mode: service:sonarqube
# Use "forwardPorts" in **devcontainer.json** to forward an app port locally.
# (Adding the "ports" property to this file will not forward from a Codespace.)
sonarqube:
image: sonarqube:lts-community
ports:
- "9000:9000"
networks:
- sonarnet
environment:
- SONARQUBE_JDBC_URL=jdbc:postgresql://db:5432/sonar
- SONARQUBE_JDBC_USERNAME=sonar
- SONARQUBE_JDBC_PASSWORD=sonar
volumes:
- sonarqube_conf:/opt/sonarqube/conf
- sonarqube_data:/opt/sonarqube/data
- sonarqube_extensions:/opt/sonarqube/extensions
- sonarqube_bundled-plugins:/opt/sonarqube/lib/bundled-plugins
db:
image: postgres
networks:
- sonarnet
environment:
- POSTGRES_USER=sonar
- POSTGRES_PASSWORD=sonar
volumes:
- postgresql:/var/lib/postgresql
- postgresql_data:/var/lib/postgresql/data
networks:
sonarnet:
driver: bridge
volumes:
sonarqube_conf:
sonarqube_data:
sonarqube_extensions:
sonarqube_bundled-plugins:
postgresql:
postgresql_data:
El primer servicio es el contenido del workspace que contiene esta configuración, para que pueda trabajar con la misma desde el Dev Container. Para poder generar este servicio, me apoyo además en un Dockerfile, con el que instalo además la línea de comandos de SonarQube:
FROM mcr.microsoft.com/devcontainers/dotnet:0-7.0
ARG SONAR_DIR=/opt/sonarscanner
# Install SonarScanner CLI
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install --no-install-recommends \
unzip \
&& rm -rf /var/lib/apt/lists/* \
&& sudo mkdir -p $SONAR_DIR && cd $SONAR_DIR \
&& sudo wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-5.0.1.3006-linux.zip \
&& sudo unzip sonar-scanner-cli-5.0.1.3006-linux.zip \
&& sudo rm sonar-scanner-cli-5.0.1.3006-linux.zip \
&& sudo chmod +x sonar-scanner-5.0.1.3006-linux/bin/sonar-scanner \
&& sudo ln -s $SONAR_DIR/sonar-scanner-5.0.1.3006-linux/bin/sonar-scanner /usr/local/bin/sonar-scanner
El segundo servicio se corresponde con el servidor de SonarQube y el último con una base de datos PostgreSQL que es donde almacenará la información de nuestros proyectos y los escaneos de los mismos.
devcontainer.json
Por último, para finalizar con la configuración, necesitas un devcontainer.json que haga de pegamento de lo anterior:
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/alpine
{
"name": "Testing SAST tools for .NET",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
// Features to add to the dev container. More info: https://containers.dev/features.
"features": {
"ghcr.io/devcontainers/features/dotnet:2": {},
"ghcr.io/devcontainers/features/java:1": {},
"ghcr.io/devcontainers-contrib/features/maven-sdkman:2": {},
"ghcr.io/devcontainers-contrib/features/snyk-cli:1": {},
"ghcr.io/devcontainers/features/docker-in-docker:2": {},
"ghcr.io/devcontainers-contrib/features/node-asdf:0": {},
"ghcr.io/devcontainers/features/go:1": {}
},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [
9000
],
"customizations": {
"vscode": {
"extensions": [
"dotenv.dotenv-vscode",
"GitHub.copilot",
"vscjava.vscode-gradle",
"golang.Go",
"ms-dotnettools.csdevkit",
"shakram02.bash-beautify"
]
}
},
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "dotnet tool install --global dotnet-sonarscanner && npm install snyk-to-html -g",
// Configure tool-specific properties.
// "customizations": {},
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
"hostRequirements": {
"cpus": 8,
"memory": "8gb"
}
}
En este caso, comol lo utilizo para diferentes lenguajes, he instalado diferentes features que me permita trabajar cómodamente con estos y también instalo, a través de la propiedad postCreateCommand, la misma herramienta sonnar-scanner a través de la línea de comandos de .NET, para que puedas probarlo también a través de esta vía si quieres.
Al abrir el proyecto como dev container podrás acceder a tu SonarQube de pruebas desde http://localhost:9000.
Si por el contrario quieres usar este servidor de pruebas para afinar tus workflows y pipelines de Azure DevOps puedes abrirlo en un Codespaces a través del botón de Code de tu repo (tienes minutos gratis al mes si es público) y lo único que tienes que hacer en la pestaña de PORTS es marcar como pública la URL que te genera y usar la misma en la configuración de tus flujos.
¡Saludos!