5349f21752
New FastAPI microservice (port 8020) providing unified blob storage via PUT/GET/DELETE/LIST HTTP API. Local filesystem backend is the default (zero extra deps). S3-compatible and WebDAV backends are built in. Backend is switchable at runtime via POST /migrate, which copies all objects to the new backend, verifies each one, atomically switches, then cleans up the old backend. WebDAV XML parsing uses defusedxml to prevent XXE attacks. Wired into docker-compose (storage_data volume) and registered in the backend service-health poller as 'storage-service'. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
139 lines
4.8 KiB
YAML
139 lines
4.8 KiB
YAML
services:
|
|
|
|
# ── Database ────────────────────────────────────────────────────────────────
|
|
db:
|
|
image: postgres:16-alpine
|
|
user: "70:70" # postgres user UID:GID in alpine image (fixed by image)
|
|
restart: unless-stopped
|
|
environment:
|
|
POSTGRES_USER: ${POSTGRES_USER:-postgres}
|
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-password}
|
|
POSTGRES_DB: ${POSTGRES_DB:-destroying_sap}
|
|
volumes:
|
|
- postgres_data:/var/lib/postgresql/data
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres}"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 10
|
|
networks:
|
|
- backend-net
|
|
|
|
# ── Storage service (unified blob storage) ──────────────────────────────────
|
|
storage-service:
|
|
build:
|
|
context: ./features/storage-service
|
|
dockerfile: Dockerfile
|
|
network: host
|
|
user: "1001:1001"
|
|
restart: unless-stopped
|
|
environment:
|
|
STORAGE_BACKEND: local
|
|
DATA_DIR: /data/storage
|
|
volumes:
|
|
- storage_data:/data/storage
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "python -c \"import urllib.request; urllib.request.urlopen('http://localhost:8020/health')\""]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
networks:
|
|
- backend-net
|
|
|
|
# ── Backend (management) ────────────────────────────────────────────────────
|
|
backend:
|
|
build:
|
|
context: ./backend
|
|
dockerfile: Dockerfile
|
|
network: host
|
|
user: "1001:1001"
|
|
restart: unless-stopped
|
|
env_file: ./backend/.env
|
|
environment:
|
|
DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-password}@db:5432/${POSTGRES_DB:-destroying_sap}
|
|
DOC_SERVICE_URL: http://doc-service:8001
|
|
AI_SERVICE_URL: http://ai-service:8010
|
|
STORAGE_SERVICE_URL: http://storage-service:8020
|
|
volumes:
|
|
- app_config:/config
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
storage-service:
|
|
condition: service_healthy
|
|
networks:
|
|
- backend-net
|
|
|
|
# ── AI service (shared AI provider intermediary) ─────────────────────────────
|
|
ai-service:
|
|
build:
|
|
context: ./features/ai-service
|
|
dockerfile: Dockerfile
|
|
network: host
|
|
user: "1001:1001"
|
|
restart: unless-stopped
|
|
environment:
|
|
CONFIG_PATH: /config/ai_service_config.json
|
|
volumes:
|
|
- app_config:/config
|
|
networks:
|
|
- backend-net
|
|
|
|
# ── Doc service (PDF extraction) ────────────────────────────────────────────
|
|
doc-service:
|
|
build:
|
|
context: ./features/doc-service
|
|
dockerfile: Dockerfile
|
|
network: host
|
|
user: "1001:1001"
|
|
restart: unless-stopped
|
|
environment:
|
|
DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-password}@db:5432/${POSTGRES_DB:-destroying_sap}
|
|
DATA_DIR: /data/documents
|
|
CONFIG_PATH: /config/doc_service_config.json
|
|
AI_SERVICE_URL: http://ai-service:8010
|
|
STORAGE_SERVICE_URL: http://storage-service:8020
|
|
volumes:
|
|
- doc_data:/data/documents
|
|
- watch_data:/data/watch
|
|
- app_config:/config
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
ai-service:
|
|
condition: service_started
|
|
storage-service:
|
|
condition: service_healthy
|
|
networks:
|
|
- backend-net
|
|
|
|
# ── Frontend (UI) ────────────────────────────────────────────────────────────
|
|
frontend:
|
|
build:
|
|
context: ./frontend
|
|
dockerfile: Dockerfile
|
|
network: host
|
|
user: "1001:1001"
|
|
restart: unless-stopped
|
|
ports:
|
|
- "80:8080"
|
|
depends_on:
|
|
- backend
|
|
networks:
|
|
- backend-net
|
|
- frontend-net
|
|
|
|
volumes:
|
|
postgres_data:
|
|
storage_data: # All file/blob storage — managed by storage-service
|
|
doc_data: # PDF files persisted across restarts (to be removed after Phase 2 migration)
|
|
watch_data: # Watch directory — bind-mount your NAS/Nextcloud here via docker-compose.override.yml
|
|
app_config: # Per-service runtime config JSON files (to be removed after Phase 3 migration)
|
|
|
|
networks:
|
|
# backend-net: db ↔ backend ↔ doc-service. No host ports bound.
|
|
# internal:true removed — doc-service needs outbound access for cloud AI providers.
|
|
backend-net:
|
|
# External-facing: only the frontend binds a host port through this network.
|
|
frontend-net:
|