feat: Dockerfile und Compose -- geschrieben, aber nie gebaut
Auf dieser Maschine gibt es weder Docker noch WSL. Das Abbild ist also ungebaut und der Container nie gelaufen; das gehoert auf eine Maschine mit Docker, bevor jemand darauf baut. Was trotzdem geprueft ist: Node 22 ist festgenagelt, und das ist kein Zufall. better-sqlite3 11.10.0 liefert fertige Binaerdateien nur fuer ABI 108 (Node 20), 115, 127 (Node 22) und 131 -- Node 24 hat ABI 137 und fehlt. Der naheliegende Griff zur neuesten Version faellt damit auf node-gyp zurueck und braucht python3, make und g++ im Abbild. Aus den Veroeffentlichungen des Projekts abgelesen, nicht aus dem Gedaechtnis. node dist/index.js -- der Startbefehl des Abbilds -- laeuft und antwortet auf /health. Bis hierher war der Dienst nur je ueber tsx gestartet worden. Der Healthcheck gibt Exitcode 0 bei laufendem und 1 bei totem Dienst. Dazu eine Falle, die im Compose steht, weil sie teuer ist: NODE_ENV=production setzt das Sitzungs-Cookie auf Secure. Wer den Container ohne HTTPS aufruft, bekommt auf die Anmeldung 200 -- und ist trotzdem nicht angemeldet, weil der Browser das Cookie still verwirft. Die naechste Anfrage ist 401. Im Browser gegen eine LAN-Adresse nachgemessen. Die naheliegende Gegenprobe ueber localhost fuehrt in die Irre: das gilt Browsern als sicherer Kontext und funktioniert. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
# Das Abbild: ein Prozess, eine Platte, sonst nichts.
|
||||
#
|
||||
# NODE 22 IST FESTGENAGELT, und das ist kein Zufall. better-sqlite3 ist ein
|
||||
# nativer Baustein und laedt beim Installieren eine fertige Binaerdatei
|
||||
# herunter (`prebuild-install || node-gyp rebuild`). Fuer 11.10.0 gibt es die
|
||||
# nur fuer diese ABI-Versionen:
|
||||
#
|
||||
# Node 20 -> ABI 115 vorhanden
|
||||
# Node 22 -> ABI 127 vorhanden <- wir
|
||||
# Node 24 -> ABI 137 FEHLT
|
||||
#
|
||||
# Wer auf 24 hochzieht, faellt auf node-gyp zurueck, und das braucht python3,
|
||||
# make und g++ im Abbild. Der Bau bricht dann ab -- laut und sofort, immerhin.
|
||||
# Vor einem Versionssprung also nachsehen, ob es die ABI als Binaerdatei gibt:
|
||||
# https://github.com/WiseLibs/better-sqlite3/releases
|
||||
#
|
||||
# bookworm-slim und nicht alpine: musl-Binaerdateien gibt es zwar auch, aber
|
||||
# der glibc-Weg ist der ausgetretene. Das Abbild ist dafuer groesser -- bei
|
||||
# einem Container auf dem eigenen Server ist das der guenstigere Tausch.
|
||||
|
||||
# ------------------------------------------------------------ Abhaengigkeiten
|
||||
FROM node:22-bookworm-slim AS deps
|
||||
WORKDIR /app
|
||||
COPY package.json package-lock.json ./
|
||||
# Nur was der Betrieb braucht. Hier laeuft prebuild-install und holt die
|
||||
# native Binaerdatei fuer diese Node-Version.
|
||||
RUN npm ci --omit=dev
|
||||
|
||||
# -------------------------------------------------------------------- Bauen
|
||||
FROM node:22-bookworm-slim AS build
|
||||
WORKDIR /app
|
||||
COPY package.json package-lock.json ./
|
||||
RUN npm ci
|
||||
COPY tsconfig.json ./
|
||||
COPY src ./src
|
||||
RUN npm run build
|
||||
|
||||
# ------------------------------------------------------------------ Betrieb
|
||||
FROM node:22-bookworm-slim AS runtime
|
||||
ENV NODE_ENV=production
|
||||
WORKDIR /app
|
||||
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY --from=build /app/dist ./dist
|
||||
COPY package.json ./
|
||||
|
||||
# Die gebaute Oberflaeche kaeme nach ./web -- der Dienst liefert sie aus, wenn
|
||||
# sie da ist, und sagt sonst, dass sie fehlt (siehe index.ts). Solange es sie
|
||||
# nicht gibt, bleibt der Ordner leer statt zu fehlen.
|
||||
RUN mkdir -p /app/web
|
||||
|
||||
# Ein Ordner fuer Bilder UND media.db, damit eine Sicherung aus genau einem
|
||||
# Kopiervorgang ueber ein Volume besteht.
|
||||
ENV DATA_DIR=/data
|
||||
RUN mkdir -p /data && chown -R node:node /data /app
|
||||
|
||||
# Nicht als root. Der Dienst nimmt Dateien von aussen entgegen und schreibt sie
|
||||
# auf die Platte -- das ist die Stelle, an der man das nicht will.
|
||||
USER node
|
||||
|
||||
ENV PORT=8080
|
||||
EXPOSE 8080
|
||||
|
||||
# Ohne curl im Abbild: Node kann das selbst, fetch ist ab 18 eingebaut.
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
||||
CMD node -e "fetch('http://127.0.0.1:'+(process.env.PORT||8080)+'/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
|
||||
|
||||
CMD ["node", "dist/index.js"]
|
||||
Reference in New Issue
Block a user