# Coolify / local — Postgres + Redis (ver plan de migración: monolito # modular panels_platform / panels_product con esquemas iam+core). # En Coolify, postgres/redis normalmente son recursos gestionados aparte # (ver docs/coolify.md); este compose incluye contenedores propios para # que `docker compose up` funcione standalone en desarrollo local. services: postgres: image: postgres:16-alpine restart: unless-stopped environment: POSTGRES_PASSWORD: ${POSTGRES_SUPERUSER_PASSWORD:?define POSTGRES_SUPERUSER_PASSWORD} volumes: - postgres-data:/var/lib/postgresql/data expose: - "5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s timeout: 5s retries: 10 redis: image: redis:7-alpine restart: unless-stopped expose: - "6379" healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 10 # Jobs de un solo uso (nunca en producción -- ver db/provision/README.md): # 1) crea roles/bases/esquemas/ACLs, 2) aplica Liquibase. `api` espera a # que ambos terminen bien antes de arrancar. provision: build: context: . dockerfile: Dockerfile.provision depends_on: postgres: condition: service_healthy redis: condition: service_healthy environment: PGHOST: postgres PGPASSWORD: ${POSTGRES_SUPERUSER_PASSWORD:?} PLATFORM_OWNER_PASSWORD: ${PLATFORM_OWNER_PASSWORD:?} PLATFORM_APP_PASSWORD: ${PLATFORM_APP_PASSWORD:?} IAM_OWNER_PASSWORD: ${IAM_OWNER_PASSWORD:?} IAM_APP_PASSWORD: ${IAM_APP_PASSWORD:?} CORE_OWNER_PASSWORD: ${CORE_OWNER_PASSWORD:?} CORE_APP_PASSWORD: ${CORE_APP_PASSWORD:?} REDIS_ADMIN_URL: redis://redis:6379 IAM_REDIS_PASSWORD: ${IAM_REDIS_PASSWORD:?} CORE_REDIS_PASSWORD: ${CORE_REDIS_PASSWORD:?} command: - -c - "./db/provision/docker-provision.sh && ./db/provision/05-redis-acl.sh" migrate: build: context: . dockerfile: Dockerfile.migrate depends_on: provision: condition: service_completed_successfully environment: DATABASE_URL_PLATFORM_OWNER: postgresql://panels_platform_owner:${PLATFORM_OWNER_PASSWORD:?}@postgres:5432/panels_platform DATABASE_URL_IAM_OWNER: postgresql://panels_iam_owner:${IAM_OWNER_PASSWORD:?}@postgres:5432/panels_product DATABASE_URL_CORE_OWNER: postgresql://panels_core_owner:${CORE_OWNER_PASSWORD:?}@postgres:5432/panels_product api: build: context: . dockerfile: Dockerfile.api restart: unless-stopped depends_on: migrate: condition: service_completed_successfully redis: condition: service_healthy environment: PORT: ${PORT:-8000} SESSION_SECRET: ${SESSION_SECRET} DOCS_KEY: ${DOCS_KEY} SEED_PASSWORD: ${SEED_PASSWORD} API_KEY: ${API_KEY:-} PANEL_LOGIN_URL: ${PANEL_LOGIN_URL} COOKIE_SECURE: ${COOKIE_SECURE:-true} CORS_ORIGINS: ${CORS_ORIGINS:-} VCARD_BASE: ${VCARD_BASE:-} SMTP_HOST: ${SMTP_HOST:-} SMTP_PORT: ${SMTP_PORT:-587} SMTP_USER: ${SMTP_USER:-} SMTP_PASS: ${SMTP_PASS:-} SMTP_FROM: ${SMTP_FROM:-} # Postgres: panels_platform (base separada) + panels_product (iam/core) DATABASE_URL_PLATFORM: postgresql://panels_platform_app:${PLATFORM_APP_PASSWORD:?}@postgres:5432/panels_platform DATABASE_URL_IAM: postgresql://panels_iam_app:${IAM_APP_PASSWORD:?}@postgres:5432/panels_product DATABASE_URL_CORE: postgresql://panels_core_app:${CORE_APP_PASSWORD:?}@postgres:5432/panels_product DATABASE_URL_IAM_OWNER: postgresql://panels_iam_owner:${IAM_OWNER_PASSWORD:?}@postgres:5432/panels_product DATABASE_URL_CORE_OWNER: postgresql://panels_core_owner:${CORE_OWNER_PASSWORD:?}@postgres:5432/panels_product # Redis: ACLs por módulo (ver db/provision/05-redis-acl.sh) REDIS_URL_IAM: redis://panels_iam_redis:${IAM_REDIS_PASSWORD:?}@redis:6379 REDIS_URL_CORE: redis://panels_core_redis:${CORE_REDIS_PASSWORD:?}@redis:6379 # Contabo Object Storage (Fase 4c) -- opcional; sin esto cae a disco # local bajo el volumen panel-data (no recomendado en producción, # ver plan: un volumen local no escala horizontalmente). S3_ENDPOINT: ${S3_ENDPOINT:-} S3_BUCKET: ${S3_BUCKET:-} S3_REGION: ${S3_REGION:-} S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:-} S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:-} volumes: - panel-data:/app/data expose: - "8000" healthcheck: test: [ "CMD", "deno", "eval", "const r=await fetch('http://127.0.0.1:'+(Deno.env.get('PORT')||'8000')+'/v1/health'); if(!r.ok) Deno.exit(1)", ] interval: 30s timeout: 5s retries: 5 start_period: 15s web-panel: build: context: . dockerfile: Dockerfile.web-panel restart: unless-stopped depends_on: api: condition: service_healthy ports: - "80" expose: - "80" web-saas: build: context: . dockerfile: Dockerfile.web-saas restart: unless-stopped depends_on: api: condition: service_healthy ports: - "80" expose: - "80" volumes: postgres-data: panel-data: