# Docker Compose for Production
# Full production setup with all services (postgres, redis, gateway, dashboard)
# Build everything into self-contained images for deployment
services:
# MCP Gateway - API Server (Production Build)
mcp-gateway:
build:
context: .
dockerfile: Dockerfile
target: production
container_name: mcp-gateway-prod
restart: unless-stopped
env_file:
- .env.docker
ports:
- "3000:3000"
environment:
# Mode
MODE: api
NODE_ENV: production
# API Configuration
API_PORT: 3000
API_HOST: 0.0.0.0
API_CORS_ORIGIN: "*"
# LLM Provider API Keys
OPENROUTER_API_KEY: ${OPENROUTER_API_KEY:-}
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-}
OPENAI_API_KEY: ${OPENAI_API_KEY:-}
# OpenRouter Configuration
OPENROUTER_FALLBACK_MODELS: ${OPENROUTER_FALLBACK_MODELS:-x-ai/grok-beta,qwen/qwen-2.5-coder-32b-instruct}
OPENROUTER_REPLACE_OPENAI: ${OPENROUTER_REPLACE_OPENAI:-openai/gpt-4o-mini}
OPENROUTER_REPLACE_CLAUDE: ${OPENROUTER_REPLACE_CLAUDE:-anthropic/claude-3.5-sonnet}
# Redis Configuration
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
REDIS_DB: 0
# Database Configuration
DB_HOST: postgres
DB_PORT: 5432
DB_NAME: ${POSTGRES_DB:-ai_mcp_gateway}
DB_USER: ${POSTGRES_USER:-postgres}
DB_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
DB_SSL: false
CONFIG_ENCRYPTION_KEY: ${CONFIG_ENCRYPTION_KEY:-L6+YmJ8xK9pQ2wR5sT1uV3yZ4aB7cD8e}
DATABASE_URL: postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@postgres:5432/${POSTGRES_DB:-ai_mcp_gateway}
# Logging
LOG_LEVEL: ${LOG_LEVEL:-info}
LOG_FILE: logs/mcp-gateway.log
# Routing Configuration
DEFAULT_LAYER: ${DEFAULT_LAYER:-L0}
ENABLE_CROSS_CHECK: ${ENABLE_CROSS_CHECK:-true}
ENABLE_AUTO_ESCALATE: ${ENABLE_AUTO_ESCALATE:-true}
MAX_ESCALATION_LAYER: ${MAX_ESCALATION_LAYER:-L2}
# Cost Tracking
ENABLE_COST_TRACKING: ${ENABLE_COST_TRACKING:-true}
COST_ALERT_THRESHOLD: ${COST_ALERT_THRESHOLD:-1.00}
volumes:
- ./logs:/app/logs
depends_on:
redis:
condition: service_healthy
postgres:
condition: service_healthy
networks:
- ai-mcp-prod
healthcheck:
test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# Redis Cache
redis:
image: redis:7-alpine
container_name: ai-mcp-redis-prod
restart: unless-stopped
ports:
- "6379:6379"
command: sh -c 'if [ -n "$$REDIS_PASSWORD" ]; then redis-server --appendonly yes --requirepass "$$REDIS_PASSWORD"; else redis-server --appendonly yes; fi'
environment:
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
volumes:
- redis-data-prod:/data
networks:
- ai-mcp-prod
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
# PostgreSQL Database
postgres:
build:
context: .
dockerfile: docker/postgres/Dockerfile
container_name: ai-mcp-postgres-prod
restart: unless-stopped
ports:
- "5432:5432"
environment:
POSTGRES_DB: ${POSTGRES_DB:-ai_mcp_gateway}
POSTGRES_USER: ${POSTGRES_USER:-postgres}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
PGDATA: /var/lib/postgresql/data/pgdata
volumes:
- postgres-data-prod:/var/lib/postgresql/data
networks:
- ai-mcp-prod
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres}"]
interval: 10s
timeout: 5s
retries: 5
# Admin Dashboard (Production Build - Static Files in Nginx)
admin-dashboard:
build:
context: .
dockerfile: admin-dashboard/Dockerfile
target: production
container_name: ai-mcp-dashboard-prod
restart: unless-stopped
ports:
- "5173:80"
depends_on:
- mcp-gateway
networks:
- ai-mcp-prod
environment:
- VITE_API_URL=http://mcp-gateway:3000
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/"]
interval: 30s
timeout: 10s
retries: 3
networks:
ai-mcp-prod:
driver: bridge
volumes:
redis-data-prod:
driver: local
postgres-data-prod:
driver: local