Production-ready deployment guide for WarDragon Analytics using Docker Compose.
- Docker Engine 20.10+
- Docker Compose 2.0+
- Minimum 2GB RAM, 50GB disk space
- Network access to WarDragon kits running DragonSync
# Clone or navigate to WarDragonAnalytics directory
cd WarDragonAnalytics
# Copy environment template
cp .env.example .env
# Edit .env with your passwords and configuration
nano .env # or vim, code, etc.# Generate database password
openssl rand -base64 32
# Generate Grafana password
openssl rand -base64 32
# Generate Grafana secret key
openssl rand -base64 32Update .env with these generated values.
Edit config/kits.yaml to define your WarDragon kits:
kits:
- id: kit-001
name: "Mobile Unit Alpha"
api_url: "http://192.168.1.100:8088"
location: "Field Operations"
enabled: true# Create and secure volume directories
mkdir -p ./volumes/timescale-data ./volumes/grafana-data
chmod 700 ./volumes/timescale-data ./volumes/grafana-data
# Grafana volume needs specific user (GID 472)
sudo chown -R 472:472 ./volumes/grafana-data# Pull images and build containers
docker-compose pull
docker-compose build
# Start all services
docker-compose up -d
# Check service status
docker-compose ps
# View logs
docker-compose logs -f# Check TimescaleDB health
docker exec wardragon-timescaledb pg_isready -U wardragon
# Check collector logs
docker-compose logs collector
# Access Web UI
curl http://localhost:8090/health
# Access Grafana
# Open browser to http://localhost:3000
# Login: admin / <your GRAFANA_PASSWORD from .env>| Service | URL | Description |
|---|---|---|
| Web UI | http://localhost:8090 | FastAPI web interface |
| Grafana | http://localhost:3000 | Grafana dashboards |
| TimescaleDB | localhost:5432 | PostgreSQL (local only) |
-
Use Strong Passwords
- Minimum 20 characters
- Mix of alphanumeric and special characters
- Use password manager
-
Network Security
- TimescaleDB bound to localhost only (already configured)
- Use reverse proxy (nginx/Traefik) for SSL/TLS
- Configure firewall (UFW/iptables)
-
Firewall Configuration
# Allow Web UI (if exposed directly) sudo ufw allow 8090/tcp # Allow Grafana (if exposed directly) sudo ufw allow 3000/tcp # For reverse proxy (nginx/Traefik) sudo ufw allow 80/tcp sudo ufw allow 443/tcp
-
CORS Configuration
- Update
CORS_ORIGINSin.envwith specific domains - Never use
*in production
- Update
-
File Permissions
# Protect sensitive files chmod 600 .env chmod 700 volumes/
Example nginx configuration for SSL termination:
# /etc/nginx/sites-available/wardragon-analytics
server {
listen 80;
server_name analytics.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name analytics.example.com;
ssl_certificate /etc/letsencrypt/live/analytics.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/analytics.example.com/privkey.pem;
# Web UI
location / {
proxy_pass http://127.0.0.1:8090;
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;
}
}
server {
listen 443 ssl http2;
server_name grafana.example.com;
ssl_certificate /etc/letsencrypt/live/grafana.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/grafana.example.com/privkey.pem;
# Grafana
location / {
proxy_pass http://127.0.0.1:3000;
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;
}
}Enable and reload:
sudo ln -s /etc/nginx/sites-available/wardragon-analytics /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx# Backup to SQL file
docker exec wardragon-timescaledb pg_dump -U wardragon wardragon > backup_$(date +%Y%m%d_%H%M%S).sql
# Backup to compressed file
docker exec wardragon-timescaledb pg_dump -U wardragon wardragon | gzip > backup_$(date +%Y%m%d_%H%M%S).sql.gz# Restore from SQL file
docker exec -i wardragon-timescaledb psql -U wardragon wardragon < backup.sql# Pull latest images
docker-compose pull
# Rebuild application containers
docker-compose build --no-cache
# Restart services
docker-compose down
docker-compose up -d# All services
docker-compose logs -f
# Specific service
docker-compose logs -f collector
docker-compose logs -f web
docker-compose logs -f grafana
# Last 100 lines
docker-compose logs --tail=100 collector# Connect to TimescaleDB
docker exec -it wardragon-timescaledb psql -U wardragon wardragon
# Check database size
SELECT pg_size_pretty(pg_database_size('wardragon'));
# Check table sizes
SELECT
schemaname,
tablename,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS size
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;
# Vacuum and analyze
VACUUM ANALYZE;# Check service status
docker-compose ps
# Check logs for errors
docker-compose logs <service-name>
# Restart specific service
docker-compose restart <service-name># Verify TimescaleDB is running
docker-compose ps timescaledb
# Check database logs
docker-compose logs timescaledb
# Test connection from collector
docker exec wardragon-collector python -c "import psycopg2; conn = psycopg2.connect('postgresql://wardragon:PASSWORD@timescaledb:5432/wardragon'); print('Connected!')"# Check collector logs
docker-compose logs -f collector
# Verify kits.yaml configuration
cat config/kits.yaml
# Test kit API manually
curl http://<kit-ip>:8088/status
curl http://<kit-ip>:8088/drones# Check Grafana logs
docker-compose logs grafana
# Verify datasource configuration
docker exec wardragon-grafana cat /etc/grafana/provisioning/datasources/timescaledb.yaml
# Test database connection from Grafana
docker exec wardragon-grafana psql -h timescaledb -U wardragon -d wardragon -c "SELECT version();"# Check Docker disk usage
docker system df
# Clean up unused resources
docker system prune -a
# Check volume sizes
du -sh volumes/*
# Check TimescaleDB data compression
docker exec wardragon-timescaledb psql -U wardragon wardragon -c "
SELECT
hypertable_name,
pg_size_pretty(before_compression_total_bytes) as before,
pg_size_pretty(after_compression_total_bytes) as after,
round(100 - (after_compression_total_bytes::numeric / before_compression_total_bytes::numeric * 100), 2) as compression_ratio
FROM timescaledb_information.hypertable_compression_stats;
"The docker-compose.yml includes optimized PostgreSQL settings. For larger deployments, consider:
# Edit docker-compose.yml timescaledb command section
shared_buffers=512MB # 25% of system RAM
effective_cache_size=2GB # 50-75% of system RAM
work_mem=16MB # Increase for complex queries
maintenance_work_mem=256MB # Increase for faster VACUUMAdjust polling intervals in .env:
# Faster polling (more database load)
POLL_INTERVAL_DRONES=2
POLL_INTERVAL_STATUS=15
# Slower polling (less load, higher latency)
POLL_INTERVAL_DRONES=10
POLL_INTERVAL_STATUS=60# Check slow queries
docker exec wardragon-timescaledb psql -U wardragon wardragon -c "
SELECT
query,
calls,
total_time,
mean_time
FROM pg_stat_statements
ORDER BY mean_time DESC
LIMIT 10;
"
# Create additional indexes if needed
# Connect to database and analyze query plans
EXPLAIN ANALYZE SELECT ...;All services include health checks. Monitor with:
# Check health status
docker-compose ps
# Watch health status continuously
watch -n 5 docker-compose ps# Monitor container resources
docker stats
# Check specific service
docker stats wardragon-collector wardragon-timescaledbSet up monitoring with Prometheus/Alertmanager (future enhancement):
- Collector polling failures
- Database connection issues
- Disk space warnings
- High query latency
Increase resources for TimescaleDB:
# docker-compose.yml
services:
timescaledb:
deploy:
resources:
limits:
cpus: '4'
memory: 8G
reservations:
cpus: '2'
memory: 4GFor high-availability deployments:
- Use TimescaleDB clustering (requires Enterprise)
- Load balance multiple collector instances
- Use external PostgreSQL cluster
For issues, check:
- Service logs:
docker-compose logs -f - Health checks:
docker-compose ps - Network connectivity:
docker network inspect wardragon-net - Database status:
docker exec wardragon-timescaledb pg_isready
See project LICENSE file.