Files
rippy/docker-compose.yml
T
Hitonabi 29444805a8
Ampel / ampel (push) Successful in 28s
fix(build): der MakeMKV-Fallback der VM war seit Monaten tot - Kette jetzt dreistufig
Beim Aufraeumen der VM-.env aufgefallen und nachgemessen (25.07.2026):

    https://www.makemkv.com/download        HTTP 200   <- Repo-Standard
    https://www.makemkv.com/download/old    HTTP 525   (Cloudflare)
    web.archive.org-Schnappschuss           HTTP 404   <- stand in der VM-.env

Die VM zeigte also auf eine KAPUTTE Adresse. Aufgefallen ist es nie, weil dort
die vendor/-Tarballs liegen und der Download-Zweig gar nicht erreicht wird.
Nimm die Tarballs weg, und jeder Bau scheitert mit 404 - waehrend die
Konfiguration gesund aussieht. Genau diese Sorte Fehler ist bei einer Uebergabe
teuer, weil sie erst beim Fremden zuschlaegt.

## Bereinigt (auf Commander-Wunsch, Sicherung liegt auf der VM)

.env.sicherung-vor-aufraeumen-20260725 angelegt, dann:
- MAKEMKV_URL_BASE raus -> es gilt der Compose-Standard, der liefert.
  Von Docker gegengeprueft: MAKEMKV_URL_BASE: https://www.makemkv.com/download
- JWT_SECRET_KEY raus -> Ueberrest der in v3.4 ausgebauten Anmeldung, wirkungslos.

## Fallbacks BEHALTEN, aber echt gemacht (Commander-Vorgabe)

Vorher war der "Fallback" eine Zeile, die man von Hand eintragen musste - und
die hier ins Leere zeigte. Jetzt eine automatische Kette:

  1. vendor/-Tarballs        (braucht kein Netz, zuverlaessigster Weg)
  2. MAKEMKV_URL_BASE
  3. MAKEMKV_URL_FALLBACK    (NEU, wird automatisch versucht wenn 2 versagt)

Stufe 3 ist ABSICHTLICH leer vorbelegt. Es gibt derzeit keine belegbare zweite
Quelle (siehe Messung oben), und eine einzutragen, die nicht liefert, waere
schlimmer als keine - genau das lag auf der VM vor. Wer eine eigene Quelle hat
(Spiegel im LAN), traegt sie ein und sie wird automatisch genutzt.

Scheitert alles, nennt die Fehlermeldung jetzt die beiden Wege, die
FUNKTIONIEREN, statt nur einen curl-Rueckgabewert zu hinterlassen.

## Geprueft, beide Zweige

- vendor-Pfad:   Bau durch, 828 MB
- Download-Pfad: im FREMDEN Klon ohne Tarballs gebaut - Bau durch, 777 MB,
  makemkvcon liegt unter /usr/local/bin/. Die leere Fallback-Stufe wird
  korrekt uebersprungen, "Erste Quelle lieferte nicht" erschien nicht.

docker compose config validiert. README und .env.example nennen die gemessenen
HTTP-Antworten, damit niemand wieder eine 404-Adresse als Fallback eintraegt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 22:50:54 +02:00

204 lines
7.5 KiB
YAML

# 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:${POSTGRES_PASSWORD:-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:-}
# Dasselbe Host-Verzeichnis wie beim Worker, nur an neutraler Stelle:
# die API liest den KEYDB-Status und die AACS-Dumps und nimmt eine
# hochgeladene KEYDB.cfg entgegen (Einstellungen → System).
- MAKEMKV_DATA_DIR=/app/makemkv-data
- 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.
# DAC_READ_SEARCH: mount.cifs hebt diese Capability an (toggle_dac_
# capability) — sie fehlt in Dockers Default-Set, ohne sie stirbt JEDER
# SMB-Mount mit "Unable to apply new capability set" (Befund 24.07.,
# auf der VM reproduziert und mit dieser Capability bewiesen behoben).
cap_add:
- SYS_ADMIN
- DAC_READ_SEARCH
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
# MakeMKV-Datenverzeichnis (dasselbe wie im Worker, siehe dort).
- ${MAKEMKV_DATA_HOST:-/srv/rippy/makemkv}:/app/makemkv-data
devices:
- ${OPTICAL_SR:-/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. /download = aktuelle Version,
# /download/old = ältere. Am 25.07.2026 nachgemessen: /download
# antwortet mit 200, /download/old mit 525 (Cloudflare), und ein
# web.archive.org-Schnappschuss mit 404 — deshalb steht hier der
# Standard, der wirklich liefert.
MAKEMKV_URL_BASE: ${MAKEMKV_URL_BASE:-https://www.makemkv.com/download}
# Zweite Quelle, die bei Fehlschlag der ersten automatisch probiert wird
# (leer = keine). Bewusst ohne Vorbelegung: eine Adresse, die nicht
# liefert, lässt die Konfiguration gesund aussehen und den Build später
# scheitern. Der zuverlässige Weg bleibt docker/worker/vendor/.
MAKEMKV_URL_FALLBACK: ${MAKEMKV_URL_FALLBACK:-}
# MakeMKV-Update OHNE Code-Änderung: neue Version in die .env,
# Tarballs nach docker/worker/vendor/ legen (oder Download klappt),
# dann docker compose build worker && docker compose up -d worker.
# Einstellungen → System meldet, wenn es eine neuere Version gibt.
MAKEMKV_VERSION: ${MAKEMKV_VERSION:-1.18.4}
environment:
- DATABASE_URL=postgresql://rippy:${POSTGRES_PASSWORD:-rippy}@postgres:5432/rippy
- REDIS_URL=redis://redis:6379/0
- RIP_OUTPUT_DIR=/app/media
- MAKEMKV_APP_KEY=${MAKEMKV_APP_KEY}
# MakeMKVs Datenverzeichnis im Container — fest verdrahtet in MakeMKV
# selbst (HOME/.MakeMKV, HOME ist /root). Steht hier, damit Worker-Code
# und Mount dieselbe Wahrheit benutzen.
- MAKEMKV_DATA_DIR=/root/.MakeMKV
# Anzeigename in Einstellungen → Worker (stabil über Rebuilds hinweg;
# via .env übersteuerbar, z. B. WORKER_NAME=wohnzimmer-vm)
- WORKER_NAME=${WORKER_NAME:-rippy-hauptworker}
# Für Serien-Episoden-Matching: der Worker fragt die API nach den
# Episoden-Laufzeiten der Staffel (TMDB).
- API_URL=http://api:8000
- LOG_LEVEL=INFO
volumes:
- type: bind
source: /srv/rippy/media
target: /app/media
bind:
propagation: rslave
- temp:/app/temp
# MakeMKV-Datenverzeichnis PERSISTENT (Befund 25.07.2026, live gemessen):
# Hier liegen die KEYDB.cfg — heute die EINZIGE funktionierende
# Schlüsselquelle für 4K-UHD, weil MakeMKVs Online-Kanal nichts mehr
# liefert —, die AACS-Dumps fehlgeschlagener Discs und settings.conf.
# Ohne diesen Mount löschte JEDER `up -d --build` beides; die
# Fehlermeldung schickte den Nutzer zu einer Datei, die es nicht mehr gab.
- ${MAKEMKV_DATA_HOST:-/srv/rippy/makemkv}:/root/.MakeMKV
devices:
# Host-Geräteknoten via .env (OPTICAL_SR/OPTICAL_SG) — je Rechner ANDERS!
# MakeMKV spricht Laufwerke über die SCSI-Generic-Schicht an; ohne den
# passenden sg-Knoten findet es „keine usable optical drives". Den sg-Knoten
# des Laufwerks auf DIESEM Host ermitteln (lsscsi -g) und in die .env eintragen.
# Achtung: nach USB-Reconnect zur Laufzeit kann die sg-Nummer wandern →
# Container neu starten. Defaults (sr0/sg1) passen für den Ursprungs-Host.
- ${OPTICAL_SR:-/dev/sr0}:/dev/sr0
- ${OPTICAL_SG:-/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=${POSTGRES_PASSWORD:-rippy}
- POSTGRES_DB=rippy
# Veröffentlicht (Befund 24.07.): Remote-Worker (GPU-Maschine, künftiger
# Windows-Worker) verbinden sich über <rippy-host>:5432/6379 — ohne
# ports: konnte sich NIE ein Remote-Worker anbinden. Heimnetz-Kompromiss,
# wie die Klartext-Credentials (README).
ports:
- "5432:5432"
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
# Siehe postgres: Pflicht für Remote-Worker (Celery-Broker).
ports:
- "6379:6379"
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: