# BrainAPI production profile: light (PostgreSQL/pgvector + Redis). x-brainapi-common: &brainapi-common image: ${BRAINAPI_IMAGE:?BRAINAPI_IMAGE is required} env_file: - ${BRAINAPI_ENV_FILE:?BRAINAPI_ENV_FILE is required} environment: &brainapi-environment ENV: production PLUGIN_FAILURE_POLICY: ${PLUGIN_FAILURE_POLICY:-fail} REDIS_HOST: redis REDIS_PORT: "6379" REDIS_PASSWORD: ${REDIS_PASSWORD:?REDIS_PASSWORD is required} POSTGRES_HOST: postgres POSTGRES_PORT: "5432" POSTGRES_USERNAME: ${POSTGRES_USERNAME:-brainapi} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required} POSTGRES_SYSTEM_DATABASE: ${POSTGRES_SYSTEM_DATABASE:-brainapi} POSTGRES_MAINTENANCE_DATABASE: postgres BRAINAPI_PLUGINS: ${BRAINAPI_PLUGINS:-} PLUGIN_REGISTRY_URL: ${PLUGIN_REGISTRY_URL:-} PLUGIN_PUBLISHER_ID: ${PLUGIN_PUBLISHER_ID:-} PLUGIN_PUBLISHER_API_KEY: ${PLUGIN_PUBLISHER_API_KEY:-} volumes: - brainapi-plugins:/app/plugins networks: [appnet] restart: unless-stopped services: nginx: image: nginx:1.28.2-alpine3.23 ports: - "80:80" - "443:443" volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx/conf.d:/etc/nginx/conf.d:ro depends_on: brainapi: condition: service_healthy brainapi-mcp: condition: service_healthy networks: [appnet] restart: unless-stopped read_only: true tmpfs: [/var/cache/nginx, /var/run, /tmp] security_opt: [no-new-privileges:true] mem_limit: 64m cpus: 0.10 healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost/health"] interval: 15s timeout: 5s retries: 5 redis: image: redis:7.4.7-alpine3.21 environment: REDIS_PASSWORD: ${REDIS_PASSWORD:?REDIS_PASSWORD is required} command: [redis-server, --requirepass, "${REDIS_PASSWORD:?REDIS_PASSWORD is required}", --appendonly, "yes", --maxmemory, 192mb, --maxmemory-policy, allkeys-lru, --save, "900 1", --save, "300 10", --save, "60 10000"] volumes: [redis-data:/data] networks: [appnet] restart: unless-stopped security_opt: [no-new-privileges:true] mem_limit: 256m cpus: 0.10 healthcheck: test: ["CMD-SHELL", "redis-cli -a \"$${REDIS_PASSWORD}\" ping 2>/dev/null | grep -q PONG"] interval: 10s timeout: 3s retries: 5 postgres: image: pgvector/pgvector:0.8.1-pg16-bookworm environment: POSTGRES_USER: ${POSTGRES_USERNAME:-brainapi} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required} POSTGRES_DB: ${POSTGRES_SYSTEM_DATABASE:-brainapi} volumes: [postgres-data:/var/lib/postgresql/data] networks: [appnet] restart: unless-stopped security_opt: [no-new-privileges:true] mem_limit: 768m cpus: 0.35 healthcheck: test: ["CMD-SHELL", "pg_isready -U \"$${POSTGRES_USER}\" -d \"$${POSTGRES_DB}\""] interval: 5s timeout: 5s retries: 12 brainapi: <<: *brainapi-common command: [-m, uvicorn, src.services.api.app:app, --host, 0.0.0.0, --port, "8000", --workers, "1", --timeout-keep-alive, "30", --limit-concurrency, "50"] depends_on: redis: {condition: service_healthy} postgres: {condition: service_healthy} mem_limit: 768m cpus: 0.50 security_opt: [no-new-privileges:true] healthcheck: test: ["CMD", "curl", "-fsS", "http://localhost:8000/health"] interval: 20s timeout: 5s retries: 8 start_period: 60s brainapi-worker: <<: *brainapi-common command: [-m, celery, -A, src.workers.app, worker, --loglevel=info, --pool=threads, --without-gossip, --without-mingle, --concurrency=1, --max-tasks-per-child=50] depends_on: redis: {condition: service_healthy} postgres: {condition: service_healthy} mem_limit: 768m cpus: 0.50 security_opt: [no-new-privileges:true] healthcheck: test: - CMD-SHELL - >- python -m celery -A src.workers.app inspect ping --timeout 5 >/dev/null 2>&1 && python -c 'import os,redis,sys; r=redis.Redis(host="redis",password=os.environ["REDIS_PASSWORD"]); sys.exit(r.llen("ingest_data") >= int(os.getenv("CELERY_QUEUE_HEALTH_THRESHOLD","50")))' interval: 30s timeout: 10s retries: 5 start_period: 90s brainapi-mcp: <<: *brainapi-common environment: <<: *brainapi-environment MCP_OAUTH_ISSUER_URL: ${MCP_OAUTH_ISSUER_URL:-} MCP_RESOURCE_SERVER_URL: ${MCP_RESOURCE_SERVER_URL:-} command: [-m, uvicorn, src.services.mcp.app:app, --host, 0.0.0.0, --port, "8001", --timeout-keep-alive, "30"] depends_on: redis: {condition: service_healthy} postgres: {condition: service_healthy} mem_limit: 768m cpus: 0.50 security_opt: [no-new-privileges:true] healthcheck: test: ["CMD", "curl", "-fsS", "http://localhost:8001/"] interval: 20s timeout: 5s retries: 5 start_period: 45s networks: appnet: driver: bridge volumes: redis-data: postgres-data: brainapi-plugins: