Full Guide to Migrating SonarQube (Docker-based) from Cloud to On-Premise


What You'll Learn
What is SonarQube and why self-host it?
How to use Docker Compose to deploy it
How to persist data using volumes
How to migrate existing data (including backups)
Common gotchas and troubleshooting
Prerequisites
Access to source server (OpenStack) and target server (On-Premise)
Docker and Docker Compose installed on both
Sufficient disk space on both servers
SonarQube running in Docker (preferably using docker-compose)
SSH access between machines or the ability to transfer
.tar.gz
files
What is SonarQube?
SonarQube is a code quality and security tool that analyzes your source code to detect bugs, vulnerabilities, and code smells. It helps maintain clean, secure, and maintainable code.
📝 You can use SonarCloud (hosted) or self-host SonarQube for more control and data privacy.
Step 1: Take a Complete Backup from Source
A. Stop the running containers to ensure data consistency:
docker compose -f sonar.yml down
B. Create a tarball of Docker volumes (including PostgreSQL and SonarQube data):
cd /var/lib/docker/volumes/
tar -czvf sonar_backup.tar.gz \
sonarqube_setup_sonarqube_data \
sonarqube_setup_sonarqube_conf \
sonarqube_setup_sonarqube_logs \
sonarqube_setup_sonarqube_extensions \
sonarqube_setup_sonarqube_bundled-plugins \
sonarqube_setup_postgresql_data
Step 2: Transfer Backup to the Target Machine
Use scp
or rsync
to transfer the tarball:
scp sonar_backup.tar.gz user@<on-prem-ip>:/home/user/
Step 3: Restore Volumes on Target Server
A. Extract volumes
cd /var/lib/docker/volumes/
sudo tar -xzvf /home/user/sonar_backup.tar.gz
B. Set correct permissions
# For SonarQube and PostgreSQL volumes
sudo chown -R 1000:1000 /var/lib/docker/volumes/sonarqube_*
Tip: UID 1000 is the default user ID inside both SonarQube and PostgreSQL containers.
Step 4: Docker Compose File
Use the same sonar.yml
or create a new one like this:
version: "3"
services:
sonarqube:
image: sonarqube:lts-community
ports:
- "9000:9000"
- "9092:9092"
depends_on:
- db
environment:
SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonar
SONAR_JDBC_USERNAME: sonar
SONAR_JDBC_PASSWORD: sonar
volumes:
- sonarqube_conf:/opt/sonarqube/conf
- sonarqube_data:/opt/sonarqube/data
- sonarqube_logs:/opt/sonarqube/logs
- sonarqube_extensions:/opt/sonarqube/extensions
- sonarqube_bundled-plugins:/opt/sonarqube/lib/bundled-plugins
networks:
sonar_network:
db:
image: postgres:10
ports:
- "5432:5432"
command: postgres -c 'max_connections=300'
volumes:
- postgresql:/var/lib/postgresql
- postgresql_data:/var/lib/postgresql/data
environment:
POSTGRES_DB: sonar
POSTGRES_USER: sonar
POSTGRES_PASSWORD: sonar
networks:
sonar_network:
restart: unless-stopped
volumes:
sonarqube_conf:
sonarqube_data:
sonarqube_logs:
sonarqube_extensions:
sonarqube_bundled-plugins:
postgresql:
postgresql_data:
networks:
sonar_network:
What’s Going On Here?
Postgres service: Stores SonarQube metadata
SonarQube service: The main app
Volumes: Help persist data across container restarts (super important for real-world usage)
restart: unless-stopped
: Ensures your containers restart automatically if the server reboots
Step 5: Start Services
docker compose -f sonar.yml up -d
Step 6: Handle Maintenance Mode
If you see:
"SonarQube is under maintenance"
It means a database upgrade is required.
Fix:
Open in browser:
http://<your-ip>:9000/setup
Click “Upgrade”. After a successful migration, you’ll be redirected to the login screen.
Final Checks
Login with admin account
Projects visible
Plugins installed
Analysis history preserved
Common Troubleshooting
Problem | Fix |
invalid command \N in SQL restore | You used COPY format SQL dump — prefer pg_dump with SQL format |
Admin password locked | Reset via DB UPDATE or recreate user using gen_random_uuid() |
SonarQube not starting | Check vm.max_map_count and set to 262144 |
"Under Maintenance" | Complete /setup page once |
Elasticsearch failed | Ensure memory is sufficient and use correct sysctl values |
Production Notes
Use
--volumes-from
or NFS mounts for persistent storage in futureAutomate daily DB + volume backup with cron +
tar
Prefer
pg_dump
for full DB-level backupsEnsure volume permission mapping if using non-root Docker host user
Learnings & Conclusion
Migrating SonarQube with Docker volumes is a clean and reliable strategy if handled carefully — particularly with:
Volume structure
Permissions
Database version compatibility
And upgrade flows post-restore
You now have an exact clone of your old setup running on your on-premise server — fully migrated and production ready.
Credits & Tools Used
Docker & Docker Compose
PostgreSQL
pg_dump
SSH / SCP / Rsync
SonarQube Docs: https://docs.sonarqube.org
Want to talk about this?
I'm open to collaboration & feedback!
Connect with me on LinkedIn or drop a ⭐ on this guide if it helped you!
Subscribe to my newsletter
Read articles from Krishank Kaushik directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
