docker.recipes

SonarQube Enterprise Stack

intermediate

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-community
4 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/data
13 - sonarqube_extensions:/opt/sonarqube/extensions
14 - sonarqube_logs:/opt/sonarqube/logs
15 depends_on:
16 postgres:
17 condition: service_healthy
18 elasticsearch:
19 condition: service_healthy
20 networks:
21 - sonar-net
22 restart: unless-stopped
23 ulimits:
24 nofile:
25 soft: 65536
26 hard: 65536
27
28 postgres:
29 image: postgres:16-alpine
30 environment:
31 POSTGRES_USER: ${POSTGRES_USER}
32 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
33 POSTGRES_DB: ${POSTGRES_DB}
34 volumes:
35 - postgres_data:/var/lib/postgresql/data
36 healthcheck:
37 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
38 interval: 10s
39 timeout: 5s
40 retries: 5
41 networks:
42 - sonar-net
43 restart: unless-stopped
44
45 elasticsearch:
46 image: elasticsearch:8.11.0
47 environment:
48 - discovery.type=single-node
49 - xpack.security.enabled=false
50 - ES_JAVA_OPTS=-Xms512m -Xmx512m
51 - bootstrap.memory_lock=true
52 volumes:
53 - es_data:/usr/share/elasticsearch/data
54 healthcheck:
55 test: ["CMD-SHELL", "curl -f http://localhost:9200/_cluster/health || exit 1"]
56 interval: 30s
57 timeout: 10s
58 retries: 5
59 networks:
60 - sonar-net
61 restart: unless-stopped
62 ulimits:
63 memlock:
64 soft: -1
65 hard: -1
66
67 nginx:
68 image: nginx:alpine
69 ports:
70 - "80:80"
71 - "443:443"
72 volumes:
73 - ./nginx.conf:/etc/nginx/nginx.conf:ro
74 - ./certs:/etc/nginx/certs:ro
75 depends_on:
76 - sonarqube
77 networks:
78 - sonar-net
79 restart: unless-stopped
80
81volumes:
82 sonarqube_data:
83 sonarqube_extensions:
84 sonarqube_logs:
85 postgres_data:
86 es_data:
87
88networks:
89 sonar-net:
90 driver: bridge

.env Template

.env
1# PostgreSQL Configuration
2POSTGRES_USER=sonar
3POSTGRES_PASSWORD=secure_postgres_password
4POSTGRES_DB=sonarqube
5
6# SonarQube settings
7SONAR_WEB_CONTEXT=/

Usage Notes

  1. 1SonarQube at http://localhost:9000
  2. 2Default login: admin/admin (change on first login)
  3. 3Configure vm.max_map_count=262144 on host
  4. 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 file
2cat > docker-compose.yml << 'EOF'
3services:
4 sonarqube:
5 image: sonarqube:lts-community
6 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/data
15 - sonarqube_extensions:/opt/sonarqube/extensions
16 - sonarqube_logs:/opt/sonarqube/logs
17 depends_on:
18 postgres:
19 condition: service_healthy
20 elasticsearch:
21 condition: service_healthy
22 networks:
23 - sonar-net
24 restart: unless-stopped
25 ulimits:
26 nofile:
27 soft: 65536
28 hard: 65536
29
30 postgres:
31 image: postgres:16-alpine
32 environment:
33 POSTGRES_USER: ${POSTGRES_USER}
34 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
35 POSTGRES_DB: ${POSTGRES_DB}
36 volumes:
37 - postgres_data:/var/lib/postgresql/data
38 healthcheck:
39 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
40 interval: 10s
41 timeout: 5s
42 retries: 5
43 networks:
44 - sonar-net
45 restart: unless-stopped
46
47 elasticsearch:
48 image: elasticsearch:8.11.0
49 environment:
50 - discovery.type=single-node
51 - xpack.security.enabled=false
52 - ES_JAVA_OPTS=-Xms512m -Xmx512m
53 - bootstrap.memory_lock=true
54 volumes:
55 - es_data:/usr/share/elasticsearch/data
56 healthcheck:
57 test: ["CMD-SHELL", "curl -f http://localhost:9200/_cluster/health || exit 1"]
58 interval: 30s
59 timeout: 10s
60 retries: 5
61 networks:
62 - sonar-net
63 restart: unless-stopped
64 ulimits:
65 memlock:
66 soft: -1
67 hard: -1
68
69 nginx:
70 image: nginx:alpine
71 ports:
72 - "80:80"
73 - "443:443"
74 volumes:
75 - ./nginx.conf:/etc/nginx/nginx.conf:ro
76 - ./certs:/etc/nginx/certs:ro
77 depends_on:
78 - sonarqube
79 networks:
80 - sonar-net
81 restart: unless-stopped
82
83volumes:
84 sonarqube_data:
85 sonarqube_extensions:
86 sonarqube_logs:
87 postgres_data:
88 es_data:
89
90networks:
91 sonar-net:
92 driver: bridge
93EOF
94
95# 2. Create the .env file
96cat > .env << 'EOF'
97# PostgreSQL Configuration
98POSTGRES_USER=sonar
99POSTGRES_PASSWORD=secure_postgres_password
100POSTGRES_DB=sonarqube
101
102# SonarQube settings
103SONAR_WEB_CONTEXT=/
104EOF
105
106# 3. Start the services
107docker compose up -d
108
109# 4. View logs
110docker compose logs -f

One-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 | bash

Troubleshooting

  • 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

Ad Space