# Docker Compose für Rippy # # Geräte-Zugriff (22.07./23.07.-Lehre): Optische Laufwerke MÜSSEN als devices: # eingebunden werden. Bind-Mounts unter volumes: geben dem Container zwar den # Geräteknoten, aber KEINE Berechtigung im Device-Cgroup → jedes open() scheitert # mit EPERM. Voraussetzung: Die VM sieht das Laufwerk (USB-Passthrough auf pve). services: api: build: context: . dockerfile: docker/api/Dockerfile environment: - DATABASE_URL=postgresql://rippy:rippy@postgres:5432/rippy - REDIS_URL=redis://redis:6379/0 - TMDB_API_KEY=${TMDB_API_KEY} - THETVDB_API_KEY=${THETVDB_API_KEY} - OMDB_API_KEY=${OMDB_API_KEY} - JWT_SECRET_KEY=${JWT_SECRET_KEY} - LOG_LEVEL=INFO healthcheck: test: ["CMD-SHELL", "python -c 'import urllib.request; urllib.request.urlopen(\"http://localhost:8000/health\")'"] interval: 30s timeout: 10s retries: 3 start_period: 10s ports: - "8000:8000" # SYS_ADMIN: die API hängt Netzwerk-Speicherziele (NFS/SMB) selbst ein # (mounts.py) — dank rshared-Propagation unten sehen Host UND Worker # jeden Mount sofort. cap_add: - SYS_ADMIN security_opt: - apparmor:unconfined volumes: # /srv/rippy/media auf der VM statt anonymem Volume: rshared lässt # Mounts aus DIESEM Container zum Host und in andere Container # propagieren (Commander-Anforderung 23.07.: Ziele frei wählbar). - type: bind source: /srv/rippy/media target: /app/media bind: propagation: rshared - temp:/app/temp devices: - /dev/sr0:/dev/sr0 networks: - rippy-net depends_on: postgres: condition: service_healthy redis: condition: service_healthy restart: unless-stopped read_only: false worker: build: context: . dockerfile: docker/worker/Dockerfile args: # Übersteuerbar via .env — makemkv.com ist zeitweise down (Cloudflare # 525); dann Wayback-Snapshot als MAKEMKV_URL_BASE eintragen. MAKEMKV_URL_BASE: ${MAKEMKV_URL_BASE:-https://www.makemkv.com/download/old} environment: - DATABASE_URL=postgresql://rippy:rippy@postgres:5432/rippy - REDIS_URL=redis://redis:6379/0 - RIP_OUTPUT_DIR=/app/media - MAKEMKV_APP_KEY=${MAKEMKV_APP_KEY} - LOG_LEVEL=INFO volumes: - type: bind source: /srv/rippy/media target: /app/media bind: propagation: rslave - temp:/app/temp devices: - /dev/sr0:/dev/sr0 # MakeMKV spricht Laufwerke über die SCSI-Generic-Schicht an — ohne den # sg-Knoten findet es „keine usable optical drives" (Deploy-Befund 23.07.). # In dieser VM: sg0 = Systemplatte, sg1 = das BD-Laufwerk. Achtung: nach # einem USB-Reconnect zur Laufzeit kann die sg-Nummer wandern → Container # neu starten. - /dev/sg1:/dev/sg1 networks: - rippy-net depends_on: postgres: condition: service_healthy redis: condition: service_healthy restart: unless-stopped # read_only bleibt Ziel (Etappe 6), aber MakeMKV/abcde brauchen HOME + # Settings — bis zur Härtung schreibbar, Ausgabe geht ohnehin aufs Volume. read_only: false tmpfs: - /app/tmp - /run - /tmp ui: build: context: . dockerfile: docker/ui/Dockerfile ports: - "80:80" networks: - rippy-net depends_on: - api restart: unless-stopped postgres: image: postgres:16-alpine environment: - POSTGRES_USER=rippy - POSTGRES_PASSWORD=rippy - POSTGRES_DB=rippy volumes: - postgres-data:/var/lib/postgresql/data networks: - rippy-net restart: unless-stopped healthcheck: test: ["CMD-SHELL", "pg_isready -U rippy -d rippy"] interval: 10s timeout: 5s retries: 5 redis: image: redis:7-alpine volumes: - redis-data:/data networks: - rippy-net restart: unless-stopped command: redis-server --appendonly yes healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 networks: rippy-net: driver: bridge volumes: temp: postgres-data: redis-data: