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
|
HEAD, Bereichsanfragen und 416 · unter dem Dateihost gibt es weder API noch
|
||||||
`/f/`-Präfix · Medienliste, Suche, Statistik nach Ordnern.
|
`/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
|
### ✅ 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
|
Dashboard-Namen zusätzlich unter `/f/` erreichbar, und unter dem Dateihost gibt
|
||||||
es weiterhin keine API.
|
es weiterhin keine API.
|
||||||
|
|
||||||
### ⬜ Als Nächstes
|
### ✅ Fertig — Schritt 2, das Abbild ist gebaut und gelaufen
|
||||||
|
|
||||||
**2 · Dockerfile und Compose — geschrieben, aber NIE GEBAUT.**
|
Gebaut, gestartet, durchgemessen — auf einer Maschine mit Docker (Desktop
|
||||||
`server/Dockerfile` und `docker-compose.media.yml` stehen. Auf der Maschine,
|
29.6.2, WSL2). Derselbe Durchstich wie in Schritt 1, diesmal gegen den
|
||||||
auf der sie entstanden sind, gibt es weder Docker noch WSL — das Abbild ist
|
**Container** statt gegen `tsx`: 24 Prüfungen, keine durchgefallen. Am
|
||||||
also ungebaut und der Container nie gelaufen. Das ist der nächste Handgriff,
|
Grundgerüst war nichts zu ändern; der Bau hat keinen einzigen Befund erzeugt.
|
||||||
und er gehört auf eine Maschine mit Docker.
|
|
||||||
|
|
||||||
Was daran trotzdem geprüft ist:
|
**So läuft er:**
|
||||||
|
|
||||||
- **Node 22 ist festgenagelt, mit Grund.** `better-sqlite3` 11.10.0 liefert
|
```bash
|
||||||
fertige Binärdateien nur für ABI 108 (Node 20), 115, 127 (Node 22) und 131.
|
export PUBLIC_URL=http://localhost:9102 ADMIN_PASSWORD=…
|
||||||
**Node 24 hat ABI 137 und fehlt** — der naheliegende Griff zur neuesten
|
docker compose -f docker-compose.media.yml up -d --build
|
||||||
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.
|
|
||||||
|
|
||||||
Ungeprüft bleibt alles, wofür es Docker braucht: ob `npm ci` im Abbild die
|
**Was jetzt gemessen ist und vorher nur behauptet war:**
|
||||||
Binärdatei zieht, ob das Volume greift, ob der Bau überhaupt durchläuft.
|
|
||||||
|
- **`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
|
> **Beim Ausprobieren:** `NODE_ENV=production` setzt das Sitzungs-Cookie auf
|
||||||
> `Secure`. Wer den Container ohne HTTPS aufruft, bekommt auf die Anmeldung
|
> `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
|
> still verwirft; die nächste Anfrage ist 401. Im Browser gegen eine
|
||||||
> LAN-Adresse nachgemessen. Die naheliegende Gegenprobe über `localhost`
|
> LAN-Adresse nachgemessen. Die naheliegende Gegenprobe über `localhost`
|
||||||
> führt in die Irre: das gilt Browsern als sicherer Kontext und funktioniert.
|
> 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**,
|
In Portainer aus diesem Repo deploybar — **`Compose path` nimmt EINE Datei**,
|
||||||
Ergänzungen werden stillschweigend ignoriert. Das hat uns bei Lite einen
|
Ergänzungen werden stillschweigend ignoriert. Das hat uns bei Lite einen
|
||||||
Nachmittag gekostet. Host-Port ist 9102, solange der Lite-Stack 9100/9101
|
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`.
|
**3 · `server/upload.lua` im Fotostudio.** `Upload.put(pfad, bytes) → url`.
|
||||||
Token in `config.upload.lua`, server-only, gitignored, mit committetem
|
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
|
- **Sicherung.** Ein Volume mit Bildern und `media.db`. Restic gegen die
|
||||||
Nextcloud? Oder reicht ein `docker cp` vor größeren Änderungen?
|
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
|
- **Bilder aus dem Spiel** (Screenshots, Clips von Spielern) — dafür brauchte
|
||||||
es Größenbegrenzungen je Token und vermutlich eine Warteschlange. Erst
|
es Größenbegrenzungen je Token und vermutlich eine Warteschlange. Erst
|
||||||
planen, wenn es ansteht.
|
planen, wenn es ansteht.
|
||||||
|
|||||||
Reference in New Issue
Block a user