Docker Cluster
The Docker Cluster deployment runs RAMP in a high-availability configuration with multiple API instances, load balancing, centralized file storage, and a Redis backplane for real-time messaging. This is the recommended setup for production environments with more than 10 users.
Architecture
Section titled “Architecture”| Component | Instances | Purpose |
|---|---|---|
| API | 3 (load balanced) | Backend application servers |
| Web UI | 2 (load balanced) | Frontend static file servers |
| Nginx | 1 | Load balancer and reverse proxy |
| PostgreSQL | 1 | Relational database |
| Redis | 1 | Cache + SignalR backplane |
| MinIO | 1 | S3-compatible file storage |
| LDAP | 1 | Enterprise authentication |
Prerequisites
Section titled “Prerequisites”- Docker Desktop 4.0+ (Windows/Mac) or Docker Engine 20.10+ (Linux)
- Docker Compose 2.0+
- Available RAM: 8 GB minimum (16 GB recommended)
- Disk Space: 20 GB minimum
# Verify installationdocker --version # 24.0.0 or higherdocker-compose --version # 2.0.0 or higherQuick start
Section titled “Quick start”-
Navigate to the RAMP directory:
Terminal window cd /path/to/RAMP -
Create a
.envfile with secure passwords:Terminal window DB_PASSWORD=YourSecureDbPassword123!LDAP_ADMIN_PASSWORD=YourLdapPassword123!LDAP_JWT_SECRET=your_jwt_secret_min_32_chars_long!JWT_SECRET=YourApiJwtSecretAtLeast32CharsLong!MINIO_ROOT_USER=adminMINIO_ROOT_PASSWORD=YourMinioPassword123! -
Start the cluster (first run takes 5—10 minutes to build images):
Terminal window docker-compose -f docker-compose.cluster.yml up -d --build -
Monitor startup progress:
Terminal window docker-compose -f docker-compose.cluster.yml psWait for all services to show
Up (healthy). Typical startup times:- Infrastructure (Redis, PostgreSQL, LDAP, MinIO): 30—60 seconds
- API instances: 60—90 seconds (includes database migrations)
- Web UI + load balancer: 10—20 seconds after APIs are healthy
-
Open your browser at http://localhost.
Default credentials
Section titled “Default credentials”RAMP admin
Section titled “RAMP admin”| Field | Value |
|---|---|
admin@ramp.local | |
| Password | Admin123! |
MinIO console (file storage)
Section titled “MinIO console (file storage)”| Field | Value |
|---|---|
| URL | http://localhost:9001 |
| Username | admin |
| Password | minio_secure_password_change_me |
Use the MinIO console to view uploaded files, create buckets, monitor storage usage, and configure access policies.
LDAP admin panel
Section titled “LDAP admin panel”| Field | Value |
|---|---|
| URL | http://localhost:17170 |
| Username | admin |
| Password | LdapAdmin123! |
PostgreSQL
Section titled “PostgreSQL”| Field | Value |
|---|---|
| Host | localhost |
| Port | 5432 |
| Database | ramp |
| Username | ramp |
| Password | RampDbPassword123! |
Connection string: postgresql://ramp:RampDbPassword123!@localhost:5432/ramp
| Field | Value |
|---|---|
| Host | localhost |
| Port | 6379 |
| Password | None (no authentication by default) |
# Connect to Redisdocker exec -it ramp-redis redis-cli
> PINGPONG> KEYS RAMP:*Verification
Section titled “Verification”After startup, verify the cluster is working correctly:
Check service health
Section titled “Check service health”docker-compose -f docker-compose.cluster.yml psExpected output: all 10 containers running, with API, database, Redis, MinIO, and LDAP showing (healthy).
Test the load balancer
Section titled “Test the load balancer”curl http://localhost/_healthTest the API via the load balancer
Section titled “Test the API via the load balancer”curl http://localhost/_api/signalrmonitoring/healthExpected response includes:
{ "status": "healthy", "signalr": { "hubsInitialized": true, "redisBackplaneEnabled": true, "redisConnected": true }}Verify SignalR real-time messaging
Section titled “Verify SignalR real-time messaging”- Open two browser windows (use different browsers or incognito mode).
- Log in to RAMP in both windows.
- Navigate to the same template in both windows.
- In Window 1, lock a field by clicking on it.
- Window 2 should immediately show the field is locked.
This works because the two windows connect to different API instances, and the lock event is broadcast through the Redis backplane.
Test instance failover
Section titled “Test instance failover”-
Open RAMP in your browser and navigate around.
-
Stop one API instance:
Terminal window docker stop ramp-api-1 -
Refresh the page. The application continues working because requests are routed to the remaining instances.
-
Restart the instance:
Terminal window docker start ramp-api-1
Test file uploads with MinIO
Section titled “Test file uploads with MinIO”- Log in to RAMP and upload an attachment to an instance.
- Open the MinIO console at http://localhost:9001.
- Verify the file appears in the
ramp-uploadsbucket. - Download the file from RAMP to confirm the round trip.
Common operations
Section titled “Common operations”View logs
Section titled “View logs”# All containersdocker-compose -f docker-compose.cluster.yml logs -f
# Specific servicedocker-compose -f docker-compose.cluster.yml logs -f ramp-api-1
# Last 100 linesdocker-compose -f docker-compose.cluster.yml logs --tail=100 ramp-api-1Restart services
Section titled “Restart services”# Restart a single instancedocker-compose -f docker-compose.cluster.yml restart ramp-api-1
# Restart all API instancesdocker-compose -f docker-compose.cluster.yml restart ramp-api-1 ramp-api-2 ramp-api-3Stop the cluster
Section titled “Stop the cluster”docker-compose -f docker-compose.cluster.yml stopdocker-compose -f docker-compose.cluster.yml down# WARNING: Deletes ALL data including database, files, and cachedocker-compose -f docker-compose.cluster.yml down -vBackup and restore
Section titled “Backup and restore”PostgreSQL
Section titled “PostgreSQL”# Plain SQLdocker exec ramp-db pg_dump -U ramp -d ramp > ramp_backup_$(date +%Y%m%d).sql
# Compresseddocker exec ramp-db pg_dump -U ramp -d ramp | gzip > ramp_backup_$(date +%Y%m%d).sql.gz# Stop API instances firstdocker-compose -f docker-compose.cluster.yml stop ramp-api-1 ramp-api-2 ramp-api-3
# Restorecat ramp_backup_20260110.sql | docker exec -i ramp-db psql -U ramp -d ramp
# Restart API instancesdocker-compose -f docker-compose.cluster.yml start ramp-api-1 ramp-api-2 ramp-api-3MinIO files
Section titled “MinIO files”# Backup MinIO datadocker exec ramp-minio tar czf - /data | cat > minio_backup_$(date +%Y%m%d).tar.gzTroubleshooting
Section titled “Troubleshooting”Containers will not start
Section titled “Containers will not start”docker-compose -f docker-compose.cluster.yml logsCommon causes:
- Ports already in use (80, 443, 5432, 6379, 9000, 17170)
- Insufficient memory (need 8 GB+ RAM)
- Docker Desktop not running
# Check port conflictslsof -i :80,5432,6379 # Linux/Macnetstat -ano | findstr "80 5432 6379" # WindowsAPI health check fails
Section titled “API health check fails”docker-compose -f docker-compose.cluster.yml logs ramp-api-1 | grep ERRORCommon causes: database migration errors, Redis connection failure, MinIO connection failure.
Solution:
# Restart infrastructure firstdocker-compose -f docker-compose.cluster.yml restart ramp-db ramp-redis ramp-minio
# Wait 30 seconds, then restart API instancesdocker-compose -f docker-compose.cluster.yml restart ramp-api-1 ramp-api-2 ramp-api-3Cannot log in
Section titled “Cannot log in”# Verify admin user existsdocker exec -it ramp-db psql -U ramp -d ramp \ -c "SELECT \"Email\", \"UserName\" FROM \"AspNetUsers\" WHERE \"Email\" = 'admin@ramp.local';"If the admin user is missing, database migrations may not have run. Check the API logs for migration errors.
SignalR not working
Section titled “SignalR not working”curl http://localhost/_api/signalrmonitoring/healthIf redisConnected is false:
# Verify Redis is runningdocker exec ramp-redis redis-cli PING# Expected: PONG
# Restart API instancesdocker-compose -f docker-compose.cluster.yml restart ramp-api-1 ramp-api-2 ramp-api-3Files not uploading
Section titled “Files not uploading”Open the MinIO console at http://localhost:9001 and check whether the ramp-uploads bucket exists. If it is missing, create it manually in the MinIO console.
LDAP authentication not working
Section titled “LDAP authentication not working”# Test LDAP connectiondocker exec ramp-ldap /app/lldap healthcheck
# View LDAP logsdocker logs ramp-ldapVerify users exist in the LDAP admin panel at http://localhost:17170 under ou=people,dc=ramp,dc=local.
Monitoring
Section titled “Monitoring”Container resource usage
Section titled “Container resource usage”# All containersdocker stats
# API instances onlydocker stats ramp-api-1 ramp-api-2 ramp-api-3Redis monitoring
Section titled “Redis monitoring”# Real-time operationsdocker exec -it ramp-redis redis-cli monitor
# Memory usagedocker exec ramp-redis redis-cli INFO memoryDatabase monitoring
Section titled “Database monitoring”docker exec -it ramp-db psql -U ramp -d ramp
-- Active connectionsSELECT count(*) FROM pg_stat_activity;
-- Database sizeSELECT pg_size_pretty(pg_database_size('ramp'));Performance tuning
Section titled “Performance tuning”Add more API instances
Section titled “Add more API instances”Edit docker-compose.cluster.yml to add ramp-api-4, ramp-api-5, etc., then:
docker-compose -f docker-compose.cluster.yml up -dIncrease PostgreSQL connections
Section titled “Increase PostgreSQL connections”Add to the ramp-db environment in docker-compose.cluster.yml:
- POSTGRES_MAX_CONNECTIONS=200Increase Redis memory
Section titled “Increase Redis memory”Edit the Redis command in docker-compose.cluster.yml:
ramp-redis: command: redis-server --appendonly yes --maxmemory 4gb --maxmemory-policy allkeys-lruRestart after making changes:
docker-compose -f docker-compose.cluster.yml restart ramp-redisProduction deployment checklist
Section titled “Production deployment checklist”- Change all default passwords (create
.envfile with secure values) - Configure SSL/TLS (add certificates to Nginx load balancer config)
- Set up automated PostgreSQL backups
- Configure external DNS (point your domain to the load balancer)
- Enable authentication for Redis (if exposed to the network)
- Review security headers in the Nginx config
- Set up monitoring (Prometheus, Grafana, or similar)
- Configure log aggregation (ELK stack, Splunk, or similar)
- Test disaster recovery (restore from backup)
- Document runbooks for your operations team