services: # Nginx reverse proxy - Main application entry point enclava-nginx: image: nginx:alpine ports: - "80:80" # Main application access (nginx proxy) volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro depends_on: - enclava-backend - enclava-frontend networks: - enclava-net restart: unless-stopped # Database migration service - runs once to apply migrations enclava-migrate: build: context: ./backend dockerfile: Dockerfile environment: - DATABASE_URL=postgresql://enclava_user:enclava_pass@enclava-postgres:5432/enclava_db - JWT_SECRET=${JWT_SECRET:-your-jwt-secret-here} depends_on: - enclava-postgres command: ["/usr/local/bin/migrate.sh"] volumes: - ./backend:/app - ./.env:/app/.env networks: - enclava-net restart: "no" # Run once and exit # Main application backend enclava-backend: build: context: ./backend dockerfile: Dockerfile environment: - DATABASE_URL=postgresql://enclava_user:enclava_pass@enclava-postgres:5432/enclava_db - REDIS_URL=redis://enclava-redis:6379 - QDRANT_HOST=enclava-qdrant - JWT_SECRET=${JWT_SECRET:-your-jwt-secret-here} - PRIVATEMODE_API_KEY=${PRIVATEMODE_API_KEY:-} - ADMIN_EMAIL=${ADMIN_EMAIL} - ADMIN_PASSWORD=${ADMIN_PASSWORD} - LOG_LLM_PROMPTS=${LOG_LLM_PROMPTS:-false} - BASE_URL=${BASE_URL} depends_on: - enclava-migrate - enclava-postgres - enclava-redis - enclava-qdrant - privatemode-proxy # Removed external port mapping - access through nginx proxy volumes: - ./backend:/app - ./logs:/app/logs - ./plugins:/plugins networks: - enclava-net restart: unless-stopped # Next.js frontend enclava-frontend: image: node:18-alpine working_dir: /app command: sh -c "npm ci --ignore-scripts && npm run dev" environment: # Required base URL (derives APP/API/WS URLs) - BASE_URL=${BASE_URL} - NEXT_PUBLIC_BASE_URL=${BASE_URL} # Docker internal ports - BACKEND_INTERNAL_PORT=${BACKEND_INTERNAL_PORT} - FRONTEND_INTERNAL_PORT=${FRONTEND_INTERNAL_PORT} # Internal API URL - INTERNAL_API_URL=http://enclava-backend:${BACKEND_INTERNAL_PORT} depends_on: - enclava-backend ports: - "3002:3000" # Direct frontend access for development volumes: - ./frontend:/app - enclava-frontend-node-modules:/app/node_modules networks: - enclava-net restart: unless-stopped dns: - 8.8.8.8 - 1.1.1.1 # PostgreSQL database enclava-postgres: image: postgres:16 environment: - POSTGRES_DB=enclava_db - POSTGRES_USER=enclava_user - POSTGRES_PASSWORD=enclava_pass volumes: - enclava-postgres-data:/var/lib/postgresql/data - ./backend/migrations:/docker-entrypoint-initdb.d networks: - enclava-net restart: unless-stopped # Redis for caching and message queue enclava-redis: image: redis:7-alpine command: redis-server --appendonly yes volumes: - enclava-redis-data:/data networks: - enclava-net restart: unless-stopped # Qdrant vector database enclava-qdrant: image: qdrant/qdrant:latest environment: - QDRANT__SERVICE__HTTP_PORT=6333 - QDRANT__SERVICE__GRPC_PORT=6334 ports: - "56333:6333" # HTTP API and Web Interface - "56334:6334" # GRPC API (optional) volumes: - enclava-qdrant-data:/qdrant/storage networks: - enclava-net restart: unless-stopped # Privatemode.ai service (optional - for confidential models) privatemode-proxy: image: ghcr.io/edgelesssys/privatemode/privatemode-proxy:latest environment: - PRIVATEMODE_API_KEY=${PRIVATEMODE_API_KEY:-} - PRIVATEMODE_CACHE_MODE=${PRIVATEMODE_CACHE_MODE:-none} - PRIVATEMODE_CACHE_SALT=${PRIVATEMODE_CACHE_SALT:-} entrypoint: ["/bin/privatemode-proxy"] command: [ "--apiKey=${PRIVATEMODE_API_KEY}", "--port=8080" ] ports: - "58080:8080" networks: - enclava-net restart: unless-stopped volumes: enclava-postgres-data: enclava-redis-data: enclava-qdrant-data: enclava-frontend-node-modules: # enclava-ollama-data: networks: enclava-net: driver: bridge