services: gateway: build: context: . dockerfile: gateway/Dockerfile ports: - "8003:8000" env_file: - .env environment: - CLIP_URL=http://clip:8000 - BLIP_URL=http://blip:8000 - YOLO_URL=http://yolo:8000 - QDRANT_SVC_URL=http://qdrant-svc:8000 - CARD_RENDERER_URL=http://card-renderer:8000 - MATURITY_URL=http://maturity:8000 - LLM_URL=${LLM_URL:-http://llm:8080} - LLM_ENABLED=${LLM_ENABLED:-false} - LLM_TIMEOUT=${LLM_TIMEOUT:-120} - LLM_DEFAULT_MODEL=${LLM_DEFAULT_MODEL:-qwen3-1.7b-instruct-q4_k_m} - LLM_MAX_TOKENS_DEFAULT=${LLM_MAX_TOKENS_DEFAULT:-256} - LLM_MAX_TOKENS_HARD_LIMIT=${LLM_MAX_TOKENS_HARD_LIMIT:-1024} - LLM_MAX_REQUEST_BYTES=${LLM_MAX_REQUEST_BYTES:-65536} - MATURITY_ENABLED=true - API_KEY=${API_KEY} - VISION_TIMEOUT=300 - MAX_IMAGE_BYTES=52428800 depends_on: clip: condition: service_healthy blip: condition: service_healthy yolo: condition: service_healthy qdrant-svc: condition: service_healthy card-renderer: condition: service_healthy maturity: condition: service_healthy healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=5).read()"] interval: 30s timeout: 10s retries: 3 start_period: 20s card-renderer: build: context: . dockerfile: card-renderer/Dockerfile environment: - CARD_DEFAULT_FONT=/app/assets/fonts/Inter-Regular.ttf - CARD_BOLD_FONT=/app/assets/fonts/Inter-Bold.ttf - CARD_LOGO_PATH=/app/assets/logo.png - CARD_MAX_IMAGE_BYTES=52428800 - CARD_DEFAULT_OUTPUT=webp - CARD_DEFAULT_QUALITY=90 healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=5).read()"] interval: 30s timeout: 10s retries: 3 start_period: 20s qdrant: image: qdrant/qdrant:latest ports: - "6333:6333" volumes: - ./data/qdrant:/qdrant/storage environment: - QDRANT__SERVICE__GRPC_PORT=6334 healthcheck: test: ["CMD-SHELL", "bash -c ':> /dev/tcp/127.0.0.1/6333' || exit 1"] interval: 30s timeout: 10s retries: 5 start_period: 15s qdrant-svc: build: context: . dockerfile: qdrant/Dockerfile environment: - QDRANT_HOST=qdrant - QDRANT_PORT=6333 - CLIP_URL=http://clip:8000 - COLLECTION_NAME=images - VECTOR_DIM=512 - SEARCH_HNSW_EF=128 depends_on: qdrant: condition: service_healthy clip: condition: service_healthy healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=5).read()"] interval: 30s timeout: 10s retries: 3 start_period: 20s clip: build: context: . dockerfile: clip/Dockerfile environment: - MODEL_NAME=ViT-B-32 - MODEL_PRETRAINED=openai healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=5).read()"] interval: 30s timeout: 10s retries: 5 start_period: 60s blip: build: context: . dockerfile: blip/Dockerfile environment: - BLIP_MODEL=Salesforce/blip-image-captioning-base #- BLIP_MODEL=Salesforce/blip-image-captioning-small healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=5).read()"] interval: 30s timeout: 10s retries: 5 start_period: 90s yolo: build: context: . dockerfile: yolo/Dockerfile environment: - YOLO_MODEL=yolov8n.pt healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=5).read()"] interval: 30s timeout: 10s retries: 5 start_period: 60s maturity: build: context: . dockerfile: maturity/Dockerfile environment: - MATURITY_MODEL=${MATURITY_MODEL:-Falconsai/nsfw_image_detection} - MATURITY_THRESHOLD_MATURE=${MATURITY_THRESHOLD_MATURE:-0.80} - MATURITY_THRESHOLD_REVIEW=${MATURITY_THRESHOLD_REVIEW:-0.60} - MAX_IMAGE_BYTES=52428800 healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=5).read()"] interval: 30s timeout: 10s retries: 5 start_period: 90s llm: build: context: . dockerfile: llm/Dockerfile environment: - MODEL_PATH=${MODEL_PATH:-/models/Qwen3-1.7B-Instruct-Q4_K_M.gguf} - LLM_MODEL_NAME=${LLM_DEFAULT_MODEL:-qwen3-1.7b-instruct-q4_k_m} - LLM_CONTEXT_SIZE=${LLM_CONTEXT_SIZE:-4096} - LLM_THREADS=${LLM_THREADS:-4} - LLM_GPU_LAYERS=${LLM_GPU_LAYERS:-0} - LLM_PORT=8080 - LLM_EXTRA_ARGS=${LLM_EXTRA_ARGS:-} volumes: - ./models/qwen3:/models:ro healthcheck: test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8080/health"] interval: 30s timeout: 10s retries: 5 start_period: 120s profiles: - llm