Files
Business-Management/docker-compose.yml
T
curo1305 5349f21752 feat: add storage-service container with pluggable backends (Phase 1)
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>
2026-04-20 15:50:31 +02:00

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: