Files
ai-drama-platform/deploy/docker-compose.production.yml

133 lines
4.3 KiB
YAML

name: ai-drama-platform
# Deployment boundary for a commercial private installation.
# The current application runtime still uses SQLite through AI_DRAMA_DB_PATH.
# PostgreSQL, Redis and S3-compatible storage are provisioned here as the
# target provider contract; switching business runtime adapters is a separate
# implementation step and must not be inferred from this compose file.
services:
postgres:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: ${POSTGRES_DB:-ai_drama}
POSTGRES_USER: ${POSTGRES_USER:-ai_drama}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 10
redis:
image: redis:7-alpine
restart: unless-stopped
command: ["redis-server", "--appendonly", "yes", "--requirepass", "${REDIS_PASSWORD:?set REDIS_PASSWORD}"]
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
interval: 10s
timeout: 5s
retries: 10
object-storage:
image: minio/minio:latest
restart: unless-stopped
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER:?set MINIO_ROOT_USER}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:?set MINIO_ROOT_PASSWORD}
volumes:
- object-storage-data:/data
ports:
- "${MINIO_API_PORT:-9000}:9000"
- "${MINIO_CONSOLE_PORT:-9001}:9001"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 10s
timeout: 5s
retries: 10
api:
build:
context: ..
dockerfile: deploy/api.Dockerfile
restart: unless-stopped
environment:
AI_DRAMA_API_PORT: 8787
AI_DRAMA_API_ORIGIN: ${PUBLIC_ORIGIN:-http://localhost}
AI_DRAMA_FRONTEND_ORIGIN: ${PUBLIC_ORIGIN:-http://localhost}
AI_DRAMA_DB_PATH: /app/data/platform.sqlite
AI_DRAMA_ALLOW_DEV_CONTEXT: "0"
AI_DRAMA_SESSION_SECRET: ${AI_DRAMA_SESSION_SECRET:?set AI_DRAMA_SESSION_SECRET}
AI_DRAMA_OIDC_STORAGE_KEY: ${AI_DRAMA_OIDC_STORAGE_KEY:?set AI_DRAMA_OIDC_STORAGE_KEY}
AI_DRAMA_MFA_ENCRYPTION_KEY: ${AI_DRAMA_MFA_ENCRYPTION_KEY:?set AI_DRAMA_MFA_ENCRYPTION_KEY}
AI_DRAMA_SAML_IDP_CERT: ${AI_DRAMA_SAML_IDP_CERT:-}
PLATFORM_POSTGRES_URL: postgresql://${POSTGRES_USER:-ai_drama}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-ai_drama}
PLATFORM_REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379/0
PLATFORM_OBJECT_STORAGE_ENDPOINT: http://object-storage:9000
PLATFORM_OBJECT_STORAGE_BUCKET: ${MINIO_BUCKET:-ai-drama}
PLATFORM_OBJECT_STORAGE_ACCESS_KEY: ${MINIO_ROOT_USER}
PLATFORM_OBJECT_STORAGE_SECRET_KEY: ${MINIO_ROOT_PASSWORD}
volumes:
- platform-data:/app/data
- platform-storage:/app/storage
- platform-exports:/app/exports
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
object-storage:
condition: service_healthy
expose:
- "8787"
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:8787/api/health').then(r => { if (!r.ok) process.exit(1) }).catch(() => process.exit(1))"]
interval: 10s
timeout: 5s
retries: 12
worker:
build:
context: ..
dockerfile: deploy/api.Dockerfile
restart: unless-stopped
command: ["npm", "run", "worker"]
environment:
AI_DRAMA_DB_PATH: /app/data/platform.sqlite
AI_DRAMA_SESSION_SECRET: ${AI_DRAMA_SESSION_SECRET:?set AI_DRAMA_SESSION_SECRET}
PLATFORM_REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379/0
volumes:
- platform-data:/app/data
- platform-storage:/app/storage
- platform-exports:/app/exports
depends_on:
api:
condition: service_healthy
frontend:
build:
context: ..
dockerfile: deploy/frontend.Dockerfile
args:
VITE_API_BASE: ${VITE_API_BASE:-}
restart: unless-stopped
ports:
- "${HTTP_PORT:-80}:80"
depends_on:
api:
condition: service_healthy
volumes:
postgres-data:
redis-data:
object-storage-data:
platform-data:
platform-storage:
platform-exports: