services: # PostgreSQL Database postgres: image: postgres:15-alpine container_name: wardrobe-db environment: POSTGRES_USER: ${POSTGRES_USER:-wardrobe} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-wardrobe} POSTGRES_DB: ${POSTGRES_DB:-wardrobe} volumes: - postgres_data:/var/lib/postgresql/data ports: - "${POSTGRES_PORT:-5432}:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-wardrobe}"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped # Redis for job queue redis: image: redis:7-alpine container_name: wardrobe-redis volumes: - redis_data:/data ports: - "${REDIS_PORT:-6379}:6379" healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped # FastAPI Backend backend: build: context: ./backend dockerfile: Dockerfile container_name: wardrobe-backend extra_hosts: - "host.docker.internal:host-gateway" environment: DEBUG: ${DEBUG:-false} DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-wardrobe}:${POSTGRES_PASSWORD:-wardrobe}@postgres:5432/${POSTGRES_DB:-wardrobe} REDIS_URL: redis://redis:6379/0 SECRET_KEY: ${SECRET_KEY:-change-me-in-production} CORS_ORIGINS: '["http://localhost:3000", "http://frontend:3000"]' STORAGE_PATH: /data/wardrobe OIDC_ISSUER_URL: ${OIDC_ISSUER_URL:-} OIDC_CLIENT_ID: ${OIDC_CLIENT_ID:-} OIDC_CLIENT_SECRET: ${OIDC_CLIENT_SECRET:-} AUTH_TRUST_HEADER: ${AUTH_TRUST_HEADER:-false} AI_BASE_URL: ${AI_BASE_URL:-http://host.docker.internal:11434/v1} AI_VISION_MODEL: ${AI_VISION_MODEL:-gpt-4o} AI_TEXT_MODEL: ${AI_TEXT_MODEL:-gpt-4o} NTFY_SERVER: ${NTFY_SERVER:-} NTFY_TOKEN: ${NTFY_TOKEN:-} MATTERMOST_WEBHOOK_URL: ${MATTERMOST_WEBHOOK_URL:-} volumes: - wardrobe_data:/data/wardrobe ports: - "${BACKEND_PORT:-8000}:8000" depends_on: postgres: condition: service_healthy redis: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/api/v1/health"] interval: 30s timeout: 10s retries: 3 restart: unless-stopped # Next.js Frontend frontend: build: context: ./frontend dockerfile: Dockerfile container_name: wardrobe-frontend environment: NEXT_PUBLIC_API_URL: http://backend:8000 NEXTAUTH_URL: ${NEXTAUTH_URL:-http://localhost:3000} NEXTAUTH_SECRET: ${NEXTAUTH_SECRET:-change-me-in-production} ports: - "${FRONTEND_PORT:-3000}:3000" depends_on: - backend restart: unless-stopped # Background Worker for AI Tagging worker: build: context: ./backend dockerfile: Dockerfile container_name: wardrobe-worker command: arq app.workers.worker.WorkerSettings extra_hosts: - "host.docker.internal:host-gateway" environment: DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-wardrobe}:${POSTGRES_PASSWORD:-wardrobe}@postgres:5432/${POSTGRES_DB:-wardrobe} REDIS_URL: redis://redis:6379/0 AI_BASE_URL: ${AI_BASE_URL:-http://host.docker.internal:11434/v1} AI_API_KEY: ${AI_API_KEY:-} AI_VISION_MODEL: ${AI_VISION_MODEL:-gpt-4o} AI_TEXT_MODEL: ${AI_TEXT_MODEL:-gpt-4o} STORAGE_PATH: /data/wardrobe volumes: - wardrobe_data:/data/wardrobe depends_on: postgres: condition: service_healthy redis: condition: service_healthy restart: unless-stopped volumes: postgres_data: redis_data: wardrobe_data: