Master the setup of SonarQube with PostgreSQL backend using Docker and Docker Compose. Learn step-by-step configuration, troubleshooting, production optimization, and best practices for code quality analysis.
SonarQube is an industry-leading static code analysis platform that continuously inspects code quality, detects bugs, security vulnerabilities, and code smells across multiple programming languages. When combined with a robust PostgreSQL database backend and Docker containerization, it creates a powerful, scalable solution for maintaining code quality in development teams.
This comprehensive guide will walk you through setting up a production-ready SonarQube instance with PostgreSQL using Docker and Docker Compose. We’ll cover everything from basic setup to advanced configuration, monitoring, and production deployment strategies.
SonarQube Advantages:
PostgreSQL Benefits:
Docker Advantages:
Minimum Requirements:
Recommended for Production:
Required Software:
Network Requirements:
Verify your environment meets the requirements:
# Check Docker installation
docker --version
docker-compose --version
# Check available memory
free -h
# Check available disk space
df -h
# Check port availability
netstat -tuln | grep -E ':9000|:5432'
SonarQube Server: The main application server that provides the web interface, processes analysis results, and manages projects and users.
PostgreSQL Database: Stores all SonarQube data including:
Docker Volumes: Persistent storage for:
[Client Browser] → [Port 9000] → [SonarQube Container]
↓
[Internal Network]
↓
[PostgreSQL Container]
Organize your SonarQube deployment with a proper directory structure:
# Create project directory
mkdir sonarqube-docker
cd sonarqube-docker
# Create subdirectories for organization
mkdir -p {config,scripts,backups}
# Create environment configuration
touch .env docker-compose.yml
Create .env file for secure credential management:
# Database Configuration
POSTGRES_USER=sonar
POSTGRES_PASSWORD=sonar_secure_password_2024
POSTGRES_DB=sonarqube
# SonarQube Configuration
SONAR_VERSION=community
SONAR_JDBC_USERNAME=sonar
SONAR_JDBC_PASSWORD=sonar_secure_password_2024
SONAR_JDBC_URL=jdbc:postgresql://db:5432/sonarqube
# Network Configuration
SONAR_PORT=9000
POSTGRES_PORT=5432
# Resource Limits
SONAR_MEMORY=2g
POSTGRES_MEMORY=1g
Security Note: Use strong, unique passwords in production and consider using Docker secrets for enhanced security.
Create docker-compose.yml with comprehensive configuration:
version: "3.8"
services:
sonarqube:
image: sonarqube:${SONAR_VERSION:-community}
container_name: sonarqube
hostname: sonarqube
depends_on:
db:
condition: service_healthy
ports:
- "${SONAR_PORT:-9000}:9000"
environment:
SONAR_JDBC_URL: ${SONAR_JDBC_URL}
SONAR_JDBC_USERNAME: ${SONAR_JDBC_USERNAME}
SONAR_JDBC_PASSWORD: ${SONAR_JDBC_PASSWORD}
SONAR_ES_BOOTSTRAP_CHECKS_DISABLE: true
volumes:
- sonarqube_data:/opt/sonarqube/data
- sonarqube_extensions:/opt/sonarqube/extensions
- sonarqube_logs:/opt/sonarqube/logs
- sonarqube_conf:/opt/sonarqube/conf
ulimits:
nofile:
soft: 65536
hard: 65536
deploy:
resources:
limits:
memory: ${SONAR_MEMORY:-2g}
reservations:
memory: 1g
restart: unless-stopped
networks:
- sonarqube-network
db:
image: postgres:15-alpine
container_name: sonarqube_db
hostname: sonarqube-db
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_INITDB_ARGS: "--encoding=UTF8 --locale=C"
volumes:
- postgresql_data:/var/lib/postgresql/data
- ./config/init-db.sql:/docker-entrypoint-initdb.d/init-db.sql:ro
ports:
- "${POSTGRES_PORT:-5432}:5432"
deploy:
resources:
limits:
memory: ${POSTGRES_MEMORY:-1g}
reservations:
memory: 512m
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 30s
timeout: 10s
retries: 5
start_period: 30s
networks:
- sonarqube-network
volumes:
sonarqube_data:
driver: local
sonarqube_extensions:
driver: local
sonarqube_logs:
driver: local
sonarqube_conf:
driver: local
postgresql_data:
driver: local
networks:
sonarqube-network:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
Service Dependencies: The depends_on with condition: service_healthy ensures SonarQube waits for PostgreSQL to be fully ready.
Health Checks: PostgreSQL health check verifies database readiness before starting dependent services.
Resource Limits: Memory limits prevent containers from consuming excessive system resources.
Ulimits: Increased file descriptor limits for SonarQube’s Elasticsearch component.
Networks: Custom network provides isolated communication between services.
Restart Policies: unless-stopped ensures containers restart automatically unless manually stopped.
Create config/init-db.sql for custom database setup:
-- Create additional schemas if needed
CREATE SCHEMA IF NOT EXISTS sonar_extensions;
-- Set optimal PostgreSQL settings for SonarQube
ALTER SYSTEM SET shared_preload_libraries = 'pg_stat_statements';
ALTER SYSTEM SET max_connections = 200;
ALTER SYSTEM SET shared_buffers = '256MB';
ALTER SYSTEM SET effective_cache_size = '1GB';
ALTER SYSTEM SET maintenance_work_mem = '64MB';
ALTER SYSTEM SET checkpoint_completion_target = 0.9;
ALTER SYSTEM SET wal_buffers = '16MB';
ALTER SYSTEM SET default_statistics_target = 100;
ALTER SYSTEM SET random_page_cost = 1.1;
-- Create a monitoring user (optional)
CREATE USER sonar_monitor WITH PASSWORD 'monitor_password';
GRANT CONNECT ON DATABASE sonarqube TO sonar_monitor;
GRANT USAGE ON SCHEMA public TO sonar_monitor;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO sonar_monitor;
-- Add comments for documentation
COMMENT ON DATABASE sonarqube IS 'SonarQube application database';
Deploy your SonarQube stack using Docker Compose:
# Start services in detached mode
docker-compose up -d
# View startup logs
docker-compose logs -f
# Check service status
docker-compose ps
Watch the logs to ensure proper startup:
# Monitor SonarQube startup
docker-compose logs -f sonarqube
# Monitor PostgreSQL startup
docker-compose logs -f db
# Check resource usage
docker stats sonarqube sonarqube_db
Expected Startup Sequence:
Verify successful deployment:
# Check container status
docker-compose ps
# Test database connectivity
docker-compose exec db psql -U sonar -d sonarqube -c "\l"
# Test SonarQube web interface
curl -I http://localhost:9000
# Check SonarQube system status
curl http://localhost:9000/api/system/status
1. Access Web Interface
http://localhost:90002. Default Credentials
adminadmin3. Mandatory Password Change
4. Setup Wizard
Security Configuration:
# Access SonarQube container for advanced configuration
docker-compose exec sonarqube bash
# View SonarQube configuration
cat /opt/sonarqube/conf/sonar.properties
Database Verification:
# Connect to PostgreSQL to verify schema creation
docker-compose exec db psql -U sonar -d sonarqube
# List SonarQube tables
\dt
# Check database size
SELECT pg_size_pretty(pg_database_size('sonarqube'));
Symptoms: SonarQube fails to start with database connection errors.
Common Causes and Solutions:
1. PostgreSQL Not Ready
# Check PostgreSQL logs
docker-compose logs db
# Verify health check status
docker-compose ps
# Manual connection test
docker-compose exec db pg_isready -U sonar
2. Incorrect Credentials
# Verify environment variables
docker-compose config
# Check database user exists
docker-compose exec db psql -U postgres -c "\du"
3. Network Issues
# Check network connectivity
docker-compose exec sonarqube ping db
# Verify DNS resolution
docker-compose exec sonarqube nslookup db
Symptoms: Slow startup, frequent crashes, or out-of-memory errors.
Solutions:
1. Increase Memory Allocation
# In docker-compose.yml
deploy:
resources:
limits:
memory: 4g
reservations:
memory: 2g
2. Elasticsearch Configuration
# Set VM max map count (Linux)
sudo sysctl -w vm.max_map_count=262144
# Make permanent
echo 'vm.max_map_count=262144' >> /etc/sysctl.conf
3. Monitor Resource Usage
# Real-time monitoring
docker stats sonarqube sonarqube_db
# Memory usage breakdown
docker-compose exec sonarqube free -h
Symptoms: Cannot bind to ports 9000 or 5432.
Solutions:
1. Check Port Usage
# Find processes using ports
sudo netstat -tulpn | grep -E ':9000|:5432'
sudo lsof -i :9000
sudo lsof -i :5432
2. Change Ports
# In .env file
SONAR_PORT=9001
POSTGRES_PORT=5433
Symptoms: Permission denied errors when accessing volumes.
Solutions:
1. Fix Volume Permissions
# Check volume ownership
docker-compose exec sonarqube ls -la /opt/sonarqube/
# Fix permissions if needed
sudo chown -R 999:999 /var/lib/docker/volumes/sonarqube-docker_sonarqube_data
2. SELinux Issues (RHEL/CentOS)
# Set SELinux context
sudo setsebool -P container_manage_cgroup on
1. Reverse Proxy Configuration
Create nginx.conf for SSL termination:
upstream sonarqube {
server localhost:9000;
}
server {
listen 80;
server_name sonarqube.yourcompany.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name sonarqube.yourcompany.com;
ssl_certificate /path/to/certificate.crt;
ssl_certificate_key /path/to/private.key;
location / {
proxy_pass http://sonarqube;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
2. Database Performance Tuning
Create config/postgresql.conf:
# Memory settings
shared_buffers = 512MB
effective_cache_size = 2GB
work_mem = 16MB
maintenance_work_mem = 128MB
# Checkpoint settings
checkpoint_completion_target = 0.9
checkpoint_timeout = 15min
# WAL settings
wal_buffers = 16MB
wal_level = replica
# Query planner settings
random_page_cost = 1.1
default_statistics_target = 100
3. Backup and Recovery
Create backup script scripts/backup.sh:
#!/bin/bash
BACKUP_DIR="/backups"
DATE=$(date +%Y%m%d_%H%M%S)
# Create backup directory
mkdir -p $BACKUP_DIR
# Backup PostgreSQL database
docker-compose exec -T db pg_dump -U sonar sonarqube | gzip > $BACKUP_DIR/sonarqube_db_$DATE.sql.gz
# Backup SonarQube data
docker-compose exec -T sonarqube tar czf - /opt/sonarqube/data > $BACKUP_DIR/sonarqube_data_$DATE.tar.gz
# Cleanup old backups (keep 7 days)
find $BACKUP_DIR -name "*.gz" -mtime +7 -delete
echo "Backup completed: $DATE"
1. Container Health Checks
# Monitor container health
watch docker-compose ps
# Check system resources
docker-compose exec sonarqube cat /proc/meminfo
docker-compose exec db cat /proc/meminfo
2. Application Monitoring
# SonarQube system status
curl http://localhost:9000/api/system/status
# Database connection count
docker-compose exec db psql -U sonar -d sonarqube -c "SELECT count(*) FROM pg_stat_activity;"
# Check SonarQube logs for errors
docker-compose logs sonarqube | grep -i error
1. Database Maintenance
-- Vacuum and analyze database
VACUUM ANALYZE;
-- Check database size
SELECT pg_size_pretty(pg_database_size('sonarqube'));
-- Monitor table sizes
SELECT schemaname,tablename,attname,n_distinct,correlation
FROM pg_stats WHERE schemaname = 'public';
2. Log Rotation
# Setup logrotate for Docker logs
cat > /etc/logrotate.d/docker << EOF
/var/lib/docker/containers/*/*.log {
rotate 7
daily
compress
missingok
delaycompress
copytruncate
}
EOF
1. Backup Before Upgrade
# Stop services
docker-compose down
# Create backup
./scripts/backup.sh
# Update version in .env
echo "SONAR_VERSION=9.9-community" >> .env
2. Perform Upgrade
# Pull new images
docker-compose pull
# Start with new version
docker-compose up -d
# Monitor upgrade process
docker-compose logs -f sonarqube
1. Database Security
2. SonarQube Security
3. Network Security
1. Docker Secrets (Swarm Mode)
version: "3.8"
services:
sonarqube:
image: sonarqube:community
secrets:
- sonar_db_password
environment:
SONAR_JDBC_PASSWORD_FILE: /run/secrets/sonar_db_password
secrets:
sonar_db_password:
external: true
2. External Secret Management
Setting up SonarQube with PostgreSQL using Docker provides a robust, scalable foundation for continuous code quality analysis. This containerized approach offers several key advantages:
The configuration presented in this guide provides a production-ready setup that can be adapted for various environments, from local development to enterprise production deployments.
Remember to regularly monitor your SonarQube instance, perform maintenance tasks, and keep both SonarQube and PostgreSQL updated to the latest stable versions for optimal security and performance.
By following the practices outlined in this guide, you’ll have a robust code quality analysis platform that helps maintain high standards across your development projects while providing valuable insights into code health and technical debt.