Skip to content

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 .env to 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

# Check status
docker-compose -f docker-compose.server.yml ps

# Resource usage
docker stats

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

# Add to Dockerfile
RUN adduser -D -u 1000 champa
USER champa

3. Read-Only Filesystem

services:
  champa-intelligence:
    read_only: true
    tmpfs:
      - /tmp
      - /app/logs

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