Docker Compose Deployment¶
Complete guide for deploying Champa Intelligence using Docker Compose in production environments.
Architecture Overview¶
Champa Intelligence uses a multi-container setup:
┌───────────────────────────────────────────┐
│ champa-intelligence (Flask/Gunicorn) │ :8088
└────────┬──────────────┬───────────────────┘
│ │
▼ ▼
┌─────────────────┐ ┌──────────────┐
│ champa-system │ │ champa-redis │
│ -db │ │ │
│ (PostgreSQL) │ │ (Cache) │
│ :5433 │ │ :6377 │
└─────────────────┘ └──────────────┘
│
▼
┌──────────────────────────┐
│ Camunda DB (External) │
│ PostgreSQL :5432 │
└──────────────────────────┘
Prerequisites¶
- Docker Engine 20.10+
- Docker Compose 2.0+
- 4GB+ RAM available
- 20GB+ disk space
- Access to Camunda PostgreSQL database
Configuration Files¶
docker-compose.server.yml¶
Purpose: Production deployment with all services
version: '3.8'
services:
# System Database
champa-system-db:
image: postgres:15-alpine
container_name: champa-system-db
environment:
POSTGRES_DB: champa_system
POSTGRES_USER: champa_user
POSTGRES_PASSWORD: ${SYSTEM_DB_PASSWORD:-champa_pass}
ports:
- "5433:5432"
volumes:
- ./postgres:/var/lib/postgresql/data
- ./init-system-db.sql:/docker-entrypoint-initdb.d/init.sql:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -U champa_user -d champa_system"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
networks:
- champa-network
# Redis Cache
champa-redis:
image: redis:7-alpine
container_name: champa-redis
command: >
redis-server
--requirepass ${REDIS_PASSWORD:-redis_pass}
--appendonly yes
--appendfsync everysec
--save 900 1
--save 300 10
--save 60 10000
ports:
- "6377:6379"
volumes:
- ./redis:/data
healthcheck:
test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
interval: 10s
timeout: 3s
retries: 3
restart: unless-stopped
networks:
- champa-network
# Champa Application
champa-intelligence:
image: champa-intelligence:latest
container_name: champa-intelligence
ports:
- "8088:8088"
volumes:
- ./config.py:/app/config.py:ro
- ./config_ai.py:/app/config_ai.py:ro
- ./logs:/app/logs
- ./tmp:/app/tmp
- static-files:/app/static
environment:
# See environment section below
- FLASK_ENV=production
# ... other variables
depends_on:
champa-system-db:
condition: service_healthy
champa-redis:
condition: service_healthy
restart: unless-stopped
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8088/health/ping')"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
networks:
- champa-network
networks:
champa-network:
driver: bridge
volumes:
static-files:
driver: local
docker-compose.yml¶
Purpose: Development/single-service deployment (app only)
Use when System DB and Redis are external or already running.
Environment Configuration¶
.env File¶
Create .env in project root:
# ============================================================
# Camunda Database (Customer DB)
# ============================================================
DB_NAME=camunda
DB_USER=camunda
DB_PASSWORD=your_secure_password_here
DB_HOST=your_camunda_host # or 10.0.1.10
DB_PORT=5432
# ============================================================
# System Database (Champa's DB)
# ============================================================
SYSTEM_DB_ENABLED=true
SYSTEM_DB_NAME=champa_system
SYSTEM_DB_USER=champa_user
SYSTEM_DB_PASSWORD=strong_password_here
SYSTEM_DB_HOST=champa-system-db
SYSTEM_DB_PORT=5432
AUTH_DB_SCHEMA=auth
# ============================================================
# Redis Configuration
# ============================================================
REDIS_ENABLED=true
REDIS_HOST=champa-redis
REDIS_PORT=6379
REDIS_PASSWORD=redis_secure_password
REDIS_DB=0
REDIS_SSL=false
REDIS_CLUSTER=false
REDIS_SESSION_TTL=3600
REDIS_CACHE_TTL=3600
# ============================================================
# Security Secrets (CHANGE THESE!)
# ============================================================
JWT_SECRET=$(openssl rand -hex 32)
JWT_EXPIRATION_HOURS=24
APP_SECRET_KEY=$(openssl rand -hex 32)
# ============================================================
# AI Configuration
# ============================================================
GOOGLE_API_KEY=your_gemini_api_key_here
# ============================================================
# Camunda REST API Access
# ============================================================
CAMUNDA_API_USER=demo
CAMUNDA_API_PASSWORD=demo
# ============================================================
# Gunicorn Configuration
# ============================================================
GUNICORN_WORKERS=4
GUNICORN_THREADS=2
GUNICORN_TIMEOUT=300
# ============================================================
# Application Configuration
# ============================================================
FLASK_ENV=production
TZ=Europe/Kiev
DEBUG=false
LOG_LEVEL=INFO
Security Best Practices¶
Generate secure secrets:
# JWT Secret
openssl rand -hex 32
# App Secret Key
openssl rand -hex 32
# Database passwords (32 characters)
openssl rand -base64 32
# Redis password
openssl rand -base64 24
Critical Security
- Never commit
.envto version control - Change all default passwords
- Use strong, unique passwords for each service
- Rotate secrets regularly (every 90 days)
Deployment Steps¶
Step 1: Prepare Environment¶
# Create project directory
mkdir -p /opt/champa-intelligence
cd /opt/champa-intelligence
# Clone repository
git clone https://github.com/your-org/champa-intelligence.git .
# Create environment file
cp .env.example .env
nano .env # Edit with your values
Step 2: Build Frontend¶
# Install Node dependencies
npm install
# Build production assets
npm run build:prod
# Verify build
ls -la static/js/dist/
Step 3: Build Docker Image¶
# Build image
docker build -t champa-intelligence:latest .
# Verify image
docker images | grep champa-intelligence
Step 4: Initialize Database¶
# Start only database services first
docker-compose -f docker-compose.server.yml up -d champa-system-db champa-redis
# Wait for health checks
docker-compose -f docker-compose.server.yml ps
# Initialize auth schema
docker exec -i champa-system-db psql -U champa_user -d champa_system <<EOF
CREATE SCHEMA IF NOT EXISTS auth;
EOF
# Initialize auth tables
docker run --rm \
--network champa-intelligence_champa-network \
-e SYSTEM_DB_HOST=champa-system-db \
-e SYSTEM_DB_NAME=champa_system \
-e SYSTEM_DB_USER=champa_user \
-e SYSTEM_DB_PASSWORD=champa_pass \
champa-intelligence:latest \
python -c "from db import init_auth_db; init_auth_db()"
Step 5: Start Application¶
# Start all services
docker-compose -f docker-compose.server.yml up -d
# Check status
docker-compose -f docker-compose.server.yml ps
# View logs
docker-compose -f docker-compose.server.yml logs -f
Step 6: Verify Deployment¶
# Health check
curl http://localhost:8088/health/ping
# Expected response:
# {"status":"OK","timestamp":"2025-01-15T10:30:00","version":"1.0.0"}
# Database health
curl http://localhost:8088/health/db
# Access UI
open http://localhost:8088
Service Management¶
Start Services¶
# Start all
docker-compose -f docker-compose.server.yml up -d
# Start specific service
docker-compose -f docker-compose.server.yml up -d champa-intelligence
Stop Services¶
# Stop all
docker-compose -f docker-compose.server.yml stop
# Stop specific
docker-compose -f docker-compose.server.yml stop champa-intelligence
Restart Services¶
# Restart all
docker-compose -f docker-compose.server.yml restart
# Restart app only
docker-compose -f docker-compose.server.yml restart champa-intelligence
View Logs¶
# All services
docker-compose -f docker-compose.server.yml logs -f
# Specific service
docker-compose -f docker-compose.server.yml logs -f champa-intelligence
# Last 100 lines
docker-compose -f docker-compose.server.yml logs --tail=100 champa-intelligence
Service Status¶
Maintenance¶
Update Application¶
# Pull latest code
git pull origin main
# Rebuild frontend
npm install
npm run build:prod
# Rebuild image
docker build -t champa-intelligence:latest .
# Restart with new image
docker-compose -f docker-compose.server.yml up -d --force-recreate champa-intelligence
Database Backup¶
# Backup system database
docker exec champa-system-db pg_dump -U champa_user champa_system > backup_$(date +%Y%m%d).sql
# Restore from backup
docker exec -i champa-system-db psql -U champa_user champa_system < backup_20250115.sql
Redis Backup¶
# Trigger save
docker exec champa-redis redis-cli -a redis_pass SAVE
# Copy dump file
docker cp champa-redis:/data/dump.rdb ./redis-backup-$(date +%Y%m%d).rdb
Clean Up¶
# Remove stopped containers
docker-compose -f docker-compose.server.yml rm
# Remove unused images
docker image prune -a
# Remove unused volumes (CAUTION: data loss!)
docker volume prune
Scaling¶
Horizontal Scaling¶
1. Add Load Balancer (Nginx):
# docker-compose.lb.yml
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- champa-1
- champa-2
networks:
- champa-network
champa-1:
extends:
file: docker-compose.server.yml
service: champa-intelligence
container_name: champa-intelligence-1
champa-2:
extends:
file: docker-compose.server.yml
service: champa-intelligence
container_name: champa-intelligence-2
ports:
- "8089:8088"
2. Nginx Configuration:
upstream champa_backend {
least_conn;
server champa-intelligence-1:8088 max_fails=3 fail_timeout=30s;
server champa-intelligence-2:8088 max_fails=3 fail_timeout=30s;
}
server {
listen 80;
server_name champa.yourcompany.com;
location / {
proxy_pass http://champa_backend;
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;
}
}
Vertical Scaling¶
Increase resources per container:
# docker-compose.override.yml
services:
champa-intelligence:
environment:
- GUNICORN_WORKERS=8
- GUNICORN_THREADS=4
deploy:
resources:
limits:
cpus: '4'
memory: 8G
reservations:
cpus: '2'
memory: 4G
Monitoring¶
Prometheus Integration¶
1. Prometheus Configuration:
# prometheus.yml
scrape_configs:
- job_name: 'champa-intelligence'
scrape_interval: 30s
static_configs:
- targets: ['champa-intelligence:8088']
metrics_path: /health/light/metrics
bearer_token: 'YOUR_API_TOKEN'
2. Add to Docker Compose:
services:
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus-data:/prometheus
ports:
- "9090:9090"
networks:
- champa-network
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana
networks:
- champa-network
Troubleshooting¶
Container Won't Start¶
# Check logs
docker logs champa-intelligence
# Common issues:
# 1. Database connection failed
docker-compose exec champa-system-db psql -U champa_user -d champa_system -c "SELECT 1;"
# 2. Redis connection failed
docker-compose exec champa-redis redis-cli -a redis_pass PING
# 3. Port already in use
sudo netstat -tlnp | grep 8088
High Memory Usage¶
# Check current usage
docker stats champa-intelligence
# Reduce workers
# Edit .env:
GUNICORN_WORKERS=2
GUNICORN_THREADS=2
# Restart
docker-compose restart champa-intelligence
Slow Performance¶
# Check Redis
docker exec champa-redis redis-cli -a redis_pass INFO stats
# Check database connections
docker exec champa-system-db psql -U champa_user -d champa_system \
-c "SELECT count(*) FROM pg_stat_activity;"
# Enable query cache
# Edit config.py and restart
Security Hardening¶
1. Use Docker Secrets¶
services:
champa-intelligence:
secrets:
- db_password
- jwt_secret
environment:
DB_PASSWORD_FILE: /run/secrets/db_password
JWT_SECRET_FILE: /run/secrets/jwt_secret
secrets:
db_password:
file: ./secrets/db_password.txt
jwt_secret:
file: ./secrets/jwt_secret.txt
2. Non-Root User¶
3. Read-Only Filesystem¶
4. Network Isolation¶
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # No external access
services:
champa-intelligence:
networks:
- frontend
- backend
champa-system-db:
networks:
- backend # Only internal access
Next Steps¶
- Nginx Configuration - Production reverse proxy setup
- Monitoring Setup - Grafana dashboards
- Backup Strategy - Automated backups
- Troubleshooting - Common issues