SonarQube Enterprise Stack
Code quality and security analysis platform with PostgreSQL and Elasticsearch.
Overview
SonarQube is a leading platform for continuous code quality inspection and security vulnerability detection, serving over 5 million developers worldwide since its launch in 2008. This enterprise-grade static analysis tool automatically reviews code for bugs, security vulnerabilities, code smells, and technical debt across 30+ programming languages including Java, C#, Python, JavaScript, and TypeScript. By integrating directly into CI/CD pipelines, SonarQube enforces quality gates that prevent problematic code from reaching production while providing detailed remediation guidance.
This comprehensive stack combines SonarQube with PostgreSQL for robust data persistence, Elasticsearch for advanced search and analytics capabilities, and NGINX for production-grade reverse proxy functionality. PostgreSQL handles SonarQube's relational data including project configurations, user management, and analysis results with full ACID compliance, while Elasticsearch powers the platform's real-time search features and complex code analytics. NGINX provides SSL termination, load balancing, and secure external access with enterprise-ready performance characteristics.
Development teams at medium to large organizations will benefit most from this configuration, particularly those implementing DevSecOps practices or managing multiple codebases with strict quality requirements. The stack is ideal for organizations transitioning from cloud-based code analysis tools to self-hosted solutions, teams requiring air-gapped deployments, or enterprises needing detailed compliance reporting and audit trails. With proper configuration, this setup can analyze millions of lines of code while maintaining sub-second search response times across historical analysis data.
Key Features
- Static code analysis across 30+ programming languages with customizable quality profiles
- Security vulnerability detection including OWASP Top 10 and CWE standards compliance
- Technical debt quantification with time-to-fix estimates and trend analysis
- Quality gates with branch analysis and pull request decoration
- Advanced search capabilities powered by Elasticsearch for code patterns and historical analysis
- PostgreSQL-backed persistence ensuring ACID compliance for critical analysis data
- Multi-project portfolio management with role-based access control
- Real-time code coverage tracking and test result integration
Common Use Cases
- 1Enterprise CI/CD pipeline integration for automated code quality enforcement
- 2Financial services organizations requiring SOX compliance and audit trail documentation
- 3Open source project maintainers managing community contributions and code standards
- 4Development teams transitioning from SonarCloud to self-hosted infrastructure
- 5Government agencies or defense contractors requiring air-gapped code analysis
- 6Multi-team organizations needing centralized code quality metrics and reporting
- 7Companies implementing DevSecOps practices with security-first development workflows
Prerequisites
- Minimum 8GB RAM available (4GB for SonarQube, 2GB for Elasticsearch, 1GB for PostgreSQL)
- Docker host with vm.max_map_count=262144 configured for Elasticsearch memory mapping
- Port availability: 9000 (SonarQube), 80/443 (NGINX), with 5432 and 9200 internal
- SSL certificates placed in ./certs directory for HTTPS-enabled NGINX configuration
- Basic understanding of static code analysis concepts and CI/CD integration patterns
- Administrative access to configure SonarQube projects and quality profiles post-deployment
For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms
docker-compose.yml
docker-compose.yml
1services: 2 sonarqube: 3 image: sonarqube:lts-community4 ports: 5 - "9000:9000"6 environment: 7 SONAR_JDBC_URL: jdbc:postgresql://postgres:5432/${POSTGRES_DB}8 SONAR_JDBC_USERNAME: ${POSTGRES_USER}9 SONAR_JDBC_PASSWORD: ${POSTGRES_PASSWORD}10 SONAR_ES_BOOTSTRAP_CHECKS_DISABLE: "true"11 volumes: 12 - sonarqube_data:/opt/sonarqube/data13 - sonarqube_extensions:/opt/sonarqube/extensions14 - sonarqube_logs:/opt/sonarqube/logs15 depends_on: 16 postgres: 17 condition: service_healthy18 elasticsearch: 19 condition: service_healthy20 networks: 21 - sonar-net22 restart: unless-stopped23 ulimits: 24 nofile: 25 soft: 6553626 hard: 655362728 postgres: 29 image: postgres:16-alpine30 environment: 31 POSTGRES_USER: ${POSTGRES_USER}32 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}33 POSTGRES_DB: ${POSTGRES_DB}34 volumes: 35 - postgres_data:/var/lib/postgresql/data36 healthcheck: 37 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]38 interval: 10s39 timeout: 5s40 retries: 541 networks: 42 - sonar-net43 restart: unless-stopped4445 elasticsearch: 46 image: elasticsearch:8.11.047 environment: 48 - discovery.type=single-node49 - xpack.security.enabled=false50 - ES_JAVA_OPTS=-Xms512m -Xmx512m51 - bootstrap.memory_lock=true52 volumes: 53 - es_data:/usr/share/elasticsearch/data54 healthcheck: 55 test: ["CMD-SHELL", "curl -f http://localhost:9200/_cluster/health || exit 1"]56 interval: 30s57 timeout: 10s58 retries: 559 networks: 60 - sonar-net61 restart: unless-stopped62 ulimits: 63 memlock: 64 soft: -165 hard: -16667 nginx: 68 image: nginx:alpine69 ports: 70 - "80:80"71 - "443:443"72 volumes: 73 - ./nginx.conf:/etc/nginx/nginx.conf:ro74 - ./certs:/etc/nginx/certs:ro75 depends_on: 76 - sonarqube77 networks: 78 - sonar-net79 restart: unless-stopped8081volumes: 82 sonarqube_data: 83 sonarqube_extensions: 84 sonarqube_logs: 85 postgres_data: 86 es_data: 8788networks: 89 sonar-net: 90 driver: bridge.env Template
.env
1# PostgreSQL Configuration2POSTGRES_USER=sonar3POSTGRES_PASSWORD=secure_postgres_password4POSTGRES_DB=sonarqube56# SonarQube settings7SONAR_WEB_CONTEXT=/Usage Notes
- 1SonarQube at http://localhost:9000
- 2Default login: admin/admin (change on first login)
- 3Configure vm.max_map_count=262144 on host
- 4Install language plugins from marketplace
Individual Services(4 services)
Copy individual services to mix and match with your existing compose files.
sonarqube
sonarqube:
image: sonarqube:lts-community
ports:
- "9000:9000"
environment:
SONAR_JDBC_URL: jdbc:postgresql://postgres:5432/${POSTGRES_DB}
SONAR_JDBC_USERNAME: ${POSTGRES_USER}
SONAR_JDBC_PASSWORD: ${POSTGRES_PASSWORD}
SONAR_ES_BOOTSTRAP_CHECKS_DISABLE: "true"
volumes:
- sonarqube_data:/opt/sonarqube/data
- sonarqube_extensions:/opt/sonarqube/extensions
- sonarqube_logs:/opt/sonarqube/logs
depends_on:
postgres:
condition: service_healthy
elasticsearch:
condition: service_healthy
networks:
- sonar-net
restart: unless-stopped
ulimits:
nofile:
soft: 65536
hard: 65536
postgres
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test:
- CMD-SHELL
- pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}
interval: 10s
timeout: 5s
retries: 5
networks:
- sonar-net
restart: unless-stopped
elasticsearch
elasticsearch:
image: elasticsearch:8.11.0
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- ES_JAVA_OPTS=-Xms512m -Xmx512m
- bootstrap.memory_lock=true
volumes:
- es_data:/usr/share/elasticsearch/data
healthcheck:
test:
- CMD-SHELL
- curl -f http://localhost:9200/_cluster/health || exit 1
interval: 30s
timeout: 10s
retries: 5
networks:
- sonar-net
restart: unless-stopped
ulimits:
memlock:
soft: -1
hard: -1
nginx
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./certs:/etc/nginx/certs:ro
depends_on:
- sonarqube
networks:
- sonar-net
restart: unless-stopped
Quick Start
terminal
1# 1. Create the compose file2cat > docker-compose.yml << 'EOF'3services:4 sonarqube:5 image: sonarqube:lts-community6 ports:7 - "9000:9000"8 environment:9 SONAR_JDBC_URL: jdbc:postgresql://postgres:5432/${POSTGRES_DB}10 SONAR_JDBC_USERNAME: ${POSTGRES_USER}11 SONAR_JDBC_PASSWORD: ${POSTGRES_PASSWORD}12 SONAR_ES_BOOTSTRAP_CHECKS_DISABLE: "true"13 volumes:14 - sonarqube_data:/opt/sonarqube/data15 - sonarqube_extensions:/opt/sonarqube/extensions16 - sonarqube_logs:/opt/sonarqube/logs17 depends_on:18 postgres:19 condition: service_healthy20 elasticsearch:21 condition: service_healthy22 networks:23 - sonar-net24 restart: unless-stopped25 ulimits:26 nofile:27 soft: 6553628 hard: 655362930 postgres:31 image: postgres:16-alpine32 environment:33 POSTGRES_USER: ${POSTGRES_USER}34 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}35 POSTGRES_DB: ${POSTGRES_DB}36 volumes:37 - postgres_data:/var/lib/postgresql/data38 healthcheck:39 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]40 interval: 10s41 timeout: 5s42 retries: 543 networks:44 - sonar-net45 restart: unless-stopped4647 elasticsearch:48 image: elasticsearch:8.11.049 environment:50 - discovery.type=single-node51 - xpack.security.enabled=false52 - ES_JAVA_OPTS=-Xms512m -Xmx512m53 - bootstrap.memory_lock=true54 volumes:55 - es_data:/usr/share/elasticsearch/data56 healthcheck:57 test: ["CMD-SHELL", "curl -f http://localhost:9200/_cluster/health || exit 1"]58 interval: 30s59 timeout: 10s60 retries: 561 networks:62 - sonar-net63 restart: unless-stopped64 ulimits:65 memlock:66 soft: -167 hard: -16869 nginx:70 image: nginx:alpine71 ports:72 - "80:80"73 - "443:443"74 volumes:75 - ./nginx.conf:/etc/nginx/nginx.conf:ro76 - ./certs:/etc/nginx/certs:ro77 depends_on:78 - sonarqube79 networks:80 - sonar-net81 restart: unless-stopped8283volumes:84 sonarqube_data:85 sonarqube_extensions:86 sonarqube_logs:87 postgres_data:88 es_data:8990networks:91 sonar-net:92 driver: bridge93EOF9495# 2. Create the .env file96cat > .env << 'EOF'97# PostgreSQL Configuration98POSTGRES_USER=sonar99POSTGRES_PASSWORD=secure_postgres_password100POSTGRES_DB=sonarqube101102# SonarQube settings103SONAR_WEB_CONTEXT=/104EOF105106# 3. Start the services107docker compose up -d108109# 4. View logs110docker compose logs -fOne-Liner
Run this command to download and set up the recipe in one step:
terminal
1curl -fsSL https://docker.recipes/api/recipes/sonarqube-enterprise/run | bashTroubleshooting
- SonarQube fails to start with 'max virtual memory areas vm.max_map_count too low': Run 'sudo sysctl -w vm.max_map_count=262144' on Docker host and add to /etc/sysctl.conf for persistence
- Elasticsearch container exits with OutOfMemoryError: Increase ES_JAVA_OPTS heap size or add more system RAM, minimum 2GB required for stable operation
- SonarQube shows 'Database connection failure' on startup: Verify PostgreSQL health check passes and POSTGRES_* environment variables match between services
- NGINX returns 502 Bad Gateway when accessing SonarQube: Check that SonarQube container is fully started (can take 60-90 seconds) and nginx.conf proxy_pass configuration is correct
- SonarQube analysis fails with 'No space left on device': Elasticsearch requires significant disk space for indexing, ensure at least 10GB free space for production usage
- Plugin installation fails in SonarQube marketplace: Restart SonarQube container after plugin installation and verify sonarqube_extensions volume has proper write permissions
Community Notes
Loading...
Loading notes...
Download Recipe Kit
Get all files in a ready-to-deploy package
Includes docker-compose.yml, .env template, README, and license
Components
sonarqubepostgresqlelasticsearchnginx
Tags
#sonarqube#code-quality#security#static-analysis#cicd
Category
DevOps & CI/CDAd Space
Shortcuts: C CopyF FavoriteD Download