docs: Schritt 2 ist gemessen -- das Abbild ist gebaut und gelaufen
Der Bau stand ungeprueft im Repo, und alles daran war Behauptung: ob `npm ci` die fertige Binaerdatei zieht, ob das Volume greift, ob der Healthcheck etwas taugt. Jetzt nachgesehen, auf einer Maschine mit Docker Desktop 29.6.2: - better-sqlite3 kommt als Binaerdatei, nicht aus node-gyp (datiert Mai 2025, kein Makefile daneben). Node 22, ABI 127 -- die Festnagelung traegt. - Derselbe Durchstich wie in Schritt 1, diesmal gegen den Container: 24 Pruefungen, keine durchgefallen. Am Grundgeruest war nichts zu aendern. - Healthcheck meldet healthy; das Volume traegt ueber einen Containerwechsel; Compose bricht ohne PUBLIC_URL/ADMIN_PASSWORD ab, wie das :? verspricht. Neu aufgefallen, weil der Container es sichtbar macht: im Volume liegen VIER Dinge, nicht zwei. SQLite laeuft im WAL-Modus, und das WAL hielt nach wenigen Uploads 152 KB, die in media.db noch nicht standen -- eine Sicherung nur ueber media.db waere unvollstaendig. Steht jetzt bei den offenen Entscheidungen. Und ein Zeuge weniger: curl taugt fuer die Secure-Cookie-Falle nicht, er schickt das Cookie auch ueber http und meldet Erfolg. Was zaehlt, ist der Browser. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+50
-19
@@ -160,7 +160,7 @@ gibt 409, Überschreiben `replaced: true` · 413 vor dem Einlesen · ETag/304,
|
||||
HEAD, Bereichsanfragen und 416 · unter dem Dateihost gibt es weder API noch
|
||||
`/f/`-Präfix · Medienliste, Suche, Statistik nach Ordnern.
|
||||
|
||||
Nicht getestet: Docker, das Dashboard (gibt es noch nicht), und echte Last.
|
||||
Nicht getestet: das Dashboard (gibt es noch nicht) und echte Last.
|
||||
|
||||
### ✅ Fertig — ein Name statt zwei
|
||||
|
||||
@@ -176,27 +176,49 @@ Beide Betriebsarten sind durchgemessen: mit einem Namen kommt
|
||||
Dashboard-Namen zusätzlich unter `/f/` erreichbar, und unter dem Dateihost gibt
|
||||
es weiterhin keine API.
|
||||
|
||||
### ⬜ Als Nächstes
|
||||
### ✅ Fertig — Schritt 2, das Abbild ist gebaut und gelaufen
|
||||
|
||||
**2 · Dockerfile und Compose — geschrieben, aber NIE GEBAUT.**
|
||||
`server/Dockerfile` und `docker-compose.media.yml` stehen. Auf der Maschine,
|
||||
auf der sie entstanden sind, gibt es weder Docker noch WSL — das Abbild ist
|
||||
also ungebaut und der Container nie gelaufen. Das ist der nächste Handgriff,
|
||||
und er gehört auf eine Maschine mit Docker.
|
||||
Gebaut, gestartet, durchgemessen — auf einer Maschine mit Docker (Desktop
|
||||
29.6.2, WSL2). Derselbe Durchstich wie in Schritt 1, diesmal gegen den
|
||||
**Container** statt gegen `tsx`: 24 Prüfungen, keine durchgefallen. Am
|
||||
Grundgerüst war nichts zu ändern; der Bau hat keinen einzigen Befund erzeugt.
|
||||
|
||||
Was daran trotzdem geprüft ist:
|
||||
**So läuft er:**
|
||||
|
||||
- **Node 22 ist festgenagelt, mit Grund.** `better-sqlite3` 11.10.0 liefert
|
||||
fertige Binärdateien nur für ABI 108 (Node 20), 115, 127 (Node 22) und 131.
|
||||
**Node 24 hat ABI 137 und fehlt** — der naheliegende Griff zur neuesten
|
||||
Version fällt auf `node-gyp` zurück und braucht python3, make und g++ im
|
||||
Abbild. Aus den Veröffentlichungen des Projekts abgelesen, nicht geraten.
|
||||
- **`node dist/index.js`** — der Startbefehl des Abbilds — läuft und antwortet
|
||||
auf `/health`. Bis dahin war der Dienst nur je über `tsx` gestartet.
|
||||
- **Der Healthcheck** gibt Exitcode 0 bei laufendem und 1 bei totem Dienst.
|
||||
```bash
|
||||
export PUBLIC_URL=http://localhost:9102 ADMIN_PASSWORD=…
|
||||
docker compose -f docker-compose.media.yml up -d --build
|
||||
```
|
||||
|
||||
Ungeprüft bleibt alles, wofür es Docker braucht: ob `npm ci` im Abbild die
|
||||
Binärdatei zieht, ob das Volume greift, ob der Bau überhaupt durchläuft.
|
||||
**Was jetzt gemessen ist und vorher nur behauptet war:**
|
||||
|
||||
- **`npm ci --omit=dev` zieht die fertige Binärdatei.** Im Abbild liegt
|
||||
`better-sqlite3/build/Release/better_sqlite3.node`, datiert Mai 2025 —
|
||||
heruntergeladen, nicht übersetzt; ein `Makefile` oder `obj.target` von
|
||||
`node-gyp` steht nirgends daneben. `require('better-sqlite3')` läuft im
|
||||
Laufzeit-Abbild, Node 22.23.2, ABI 127. **Die Festnagelung trägt.**
|
||||
- **Der Bau läuft durch**, alle drei Stufen. Das Abbild: 373 MB auf der
|
||||
Platte, 88,4 MB Inhalt.
|
||||
- **Der Healthcheck greift.** Docker meldet `healthy`, Exitcode 0, kein
|
||||
Fehlschlag — ohne `curl` im Abbild, `fetch` aus Node reicht.
|
||||
- **Das Volume greift.** Container weggeworfen, einen neuen an dasselbe
|
||||
Volume gehängt: die Datei aus dem ersten kommt weiter unter ihrer URL, und
|
||||
`admin` wird nicht noch einmal angelegt. Nebenbei bestätigt, was im Compose
|
||||
steht: ein geändertes `ADMIN_PASSWORD` setzt nichts zurück — die alte
|
||||
Anmeldung gilt (200), die neue nicht (401).
|
||||
- **Compose bricht ohne Variablen ab**, wie das `:?` verspricht, und zwar mit
|
||||
dem Text, der danebensteht — erst `PUBLIC_URL`, dann `ADMIN_PASSWORD`. Mit
|
||||
beiden fährt der Stack hoch und bindet `0.0.0.0:9102->8080`.
|
||||
- **`Secure` steht wirklich im Cookie**, wenn `NODE_ENV=production` gilt:
|
||||
`sid=…; Path=/; HttpOnly; Secure; SameSite=Lax`. Ohne Cookie oder mit einem
|
||||
erfundenen gibt jede Dashboard-Route 401 — auch `/auth/me`.
|
||||
|
||||
**Neu aufgefallen, weil der Container es sichtbar macht:** im Volume liegen
|
||||
**vier** Dinge, nicht zwei — `files/`, `media.db`, `media.db-shm` und
|
||||
`media.db-wal`. SQLite läuft im WAL-Modus (`db.ts`), und das WAL war nach
|
||||
wenigen Uploads 152 KB groß, mit Daten, die in `media.db` noch nicht standen.
|
||||
Eine Sicherung, die nur `media.db` mitnimmt, ist deshalb unvollständig. Siehe
|
||||
*Offene Entscheidungen*.
|
||||
|
||||
> **Beim Ausprobieren:** `NODE_ENV=production` setzt das Sitzungs-Cookie auf
|
||||
> `Secure`. Wer den Container ohne HTTPS aufruft, bekommt auf die Anmeldung
|
||||
@@ -204,11 +226,16 @@ Binärdatei zieht, ob das Volume greift, ob der Bau überhaupt durchläuft.
|
||||
> still verwirft; die nächste Anfrage ist 401. Im Browser gegen eine
|
||||
> LAN-Adresse nachgemessen. Die naheliegende Gegenprobe über `localhost`
|
||||
> führt in die Irre: das gilt Browsern als sicherer Kontext und funktioniert.
|
||||
> Und `curl` taugt hier nicht als Zeuge — der schickt ein Secure-Cookie auch
|
||||
> über `http` und meldet fröhlich Erfolg. Was zählt, ist der Browser.
|
||||
|
||||
In Portainer aus diesem Repo deploybar — **`Compose path` nimmt EINE Datei**,
|
||||
Ergänzungen werden stillschweigend ignoriert. Das hat uns bei Lite einen
|
||||
Nachmittag gekostet. Host-Port ist 9102, solange der Lite-Stack 9100/9101
|
||||
belegt.
|
||||
belegt. **Auf dem Server selbst ist noch nicht deployt** — gebaut und gelaufen
|
||||
ist auf der Arbeitsmaschine. Das ist Schritt 5.
|
||||
|
||||
### ⬜ Als Nächstes
|
||||
|
||||
**3 · `server/upload.lua` im Fotostudio.** `Upload.put(pfad, bytes) → url`.
|
||||
Token in `config.upload.lua`, server-only, gitignored, mit committetem
|
||||
@@ -247,6 +274,10 @@ Lite-Stack als Vergleichsmaßstab laufen.
|
||||
|
||||
- **Sicherung.** Ein Volume mit Bildern und `media.db`. Restic gegen die
|
||||
Nextcloud? Oder reicht ein `docker cp` vor größeren Änderungen?
|
||||
**Was dabei feststeht:** wegen WAL gehören `media.db-wal` und `media.db-shm`
|
||||
mit ins Kopieren, sonst fehlen die letzten Uploads. Sauberer wäre
|
||||
`sqlite3 media.db ".backup …"` oder ein `wal_checkpoint(TRUNCATE)` davor —
|
||||
beides ungeprüft, weil noch nicht entschieden ist, wie gesichert wird.
|
||||
- **Bilder aus dem Spiel** (Screenshots, Clips von Spielern) — dafür brauchte
|
||||
es Größenbegrenzungen je Token und vermutlich eine Warteschlange. Erst
|
||||
planen, wenn es ansteht.
|
||||
|
||||
Reference in New Issue
Block a user