Das Verzeichnis scripts/ wurde beim Bauen nie in die Laufzeitstufe
uebernommen. Der in der Anleitung dokumentierte Befehl
docker compose exec app node scripts/totp-geheimnis.mjs ...
endete deshalb mit "Cannot find module". Betroffen war nicht nur dieses
eine Skript, sondern alle, die im laufenden Behaelter gedacht sind - auch
wartungsschluessel.mjs und schluessel-erzeugen.mjs.
Kopiert wird jetzt das ganze Verzeichnis, nicht einzelne Dateien. Sonst
faellt beim naechsten Betriebsskript wieder auf, dass es fehlt - und zwar
erst dann, wenn man es braucht. Die Entwicklungsskripte darin laufen dort
mangels Werkzeugen nicht, kosten aber nur ein paar Kilobyte.
Geprueft im fertigen Abbild und gegen eine echte Datenbank: Das Skript
liegt unter /app/scripts, laeuft als Benutzer cockpit und gibt dasselbe
Geheimnis aus wie auf dem Entwicklungsrechner.
Die Anleitung nennt jetzt zusaetzlich den Weg fuer alle, die noch eine
aeltere Fassung laufen haben und nicht sofort aktualisieren wollen:
docker compose cp legt die Datei einmalig in den Behaelter.
Etappe: 8
Phase: Haertung
119 lines
4.6 KiB
Docker
119 lines
4.6 KiB
Docker
# =============================================================================
|
|
# Betreuungs-Cockpit - Produktionsabbild
|
|
# =============================================================================
|
|
#
|
|
# Drei Stufen, damit im laufenden Abbild weder Quelltext noch Bauwerkzeuge
|
|
# liegen. Das Ergebnis sind rund 580 MB - der groesste Anteil davon sind
|
|
# Tesseract mit den deutschen Sprachdaten und die Prisma-Engines.
|
|
#
|
|
# Geprueft im fertigen Abbild: Node 22, Zeitzone Europe/Berlin,
|
|
# tesseract 5.5.2 mit Sprache deu, pdftoppm aus poppler-utils, Lauf als
|
|
# Benutzer cockpit (uid 1001), Migrationen und SQL-Skripte an Bord.
|
|
#
|
|
# Basis ist Alpine: kleiner Angriffsflaeche, und @node-rs/argon2 sowie
|
|
# Prisma bringen fertige musl-Binaerdateien mit.
|
|
# =============================================================================
|
|
|
|
# --- Stufe 1: Abhaengigkeiten -----------------------------------------------
|
|
FROM node:22-alpine AS abhaengigkeiten
|
|
WORKDIR /app
|
|
|
|
# Prisma und OpenSSL gehoeren zusammen.
|
|
RUN apk add --no-cache libc6-compat openssl
|
|
|
|
COPY package.json package-lock.json ./
|
|
COPY prisma ./prisma
|
|
|
|
# "npm ci" mit dem Lockfile - reproduzierbar, keine Ueberraschungen beim
|
|
# naechsten Bau. Der postinstall-Schritt erzeugt den Prisma-Client.
|
|
RUN npm ci --ignore-scripts \
|
|
&& npx prisma generate
|
|
|
|
# --- Stufe 2: Bauen ----------------------------------------------------------
|
|
FROM node:22-alpine AS bau
|
|
WORKDIR /app
|
|
|
|
RUN apk add --no-cache libc6-compat openssl
|
|
|
|
COPY --from=abhaengigkeiten /app/node_modules ./node_modules
|
|
COPY . .
|
|
|
|
# Beim Bauen werden keine echten Geheimnisse gebraucht: src/lib/env.ts
|
|
# prueft erst beim Zugriff. Diese Platzhalter erfuellen nur die Typen.
|
|
ENV NEXT_TELEMETRY_DISABLED=1
|
|
ENV SKIP_ENV_VALIDATION=1
|
|
|
|
# Git-Stand und Bauzeitpunkt landen in der Oberflaeche und im
|
|
# Gesundheitsendpunkt. Beim Aktualisieren sieht man damit auf einen Blick,
|
|
# ob wirklich der neue Stand laeuft:
|
|
#
|
|
# docker build --build-arg GIT_COMMIT=$(git rev-parse --short HEAD) .
|
|
ARG GIT_COMMIT=""
|
|
ARG BUILD_ZEIT=""
|
|
ENV NEXT_PUBLIC_GIT_COMMIT=$GIT_COMMIT
|
|
ENV NEXT_PUBLIC_BUILD_ZEIT=$BUILD_ZEIT
|
|
|
|
RUN npm run build
|
|
|
|
# --- Stufe 3: Laufzeit -------------------------------------------------------
|
|
FROM node:22-alpine AS laufzeit
|
|
WORKDIR /app
|
|
|
|
# tesseract-ocr + deutsche Sprachdaten fuer die Texterkennung,
|
|
# poppler-utils fuer pdftoppm (PDF-Seiten zu Bildern),
|
|
# tzdata fuer Europe/Berlin - sonst rechnet der Server in UTC und
|
|
# verschiebt Fristen um einen Tag.
|
|
RUN apk add --no-cache \
|
|
libc6-compat \
|
|
openssl \
|
|
tzdata \
|
|
tesseract-ocr \
|
|
tesseract-ocr-data-deu \
|
|
poppler-utils \
|
|
&& cp /usr/share/zoneinfo/Europe/Berlin /etc/localtime \
|
|
&& echo "Europe/Berlin" > /etc/timezone
|
|
|
|
ENV NODE_ENV=production
|
|
ENV NEXT_TELEMETRY_DISABLED=1
|
|
ENV TZ=Europe/Berlin
|
|
ENV PORT=3000
|
|
ENV HOSTNAME=0.0.0.0
|
|
|
|
# Nicht als root laufen.
|
|
RUN addgroup --system --gid 1001 cockpit \
|
|
&& adduser --system --uid 1001 --ingroup cockpit cockpit
|
|
|
|
# Der Standalone-Build von Next.js bringt nur mit, was wirklich gebraucht wird.
|
|
COPY --from=bau --chown=cockpit:cockpit /app/.next/standalone ./
|
|
COPY --from=bau --chown=cockpit:cockpit /app/.next/static ./.next/static
|
|
COPY --from=bau --chown=cockpit:cockpit /app/public ./public
|
|
|
|
# Prisma-Schema, Migrationen und SQL-Skripte fuer "prisma migrate deploy"
|
|
# im laufenden Behaelter.
|
|
COPY --from=bau --chown=cockpit:cockpit /app/prisma ./prisma
|
|
COPY --from=bau --chown=cockpit:cockpit /app/node_modules/.prisma ./node_modules/.prisma
|
|
COPY --from=bau --chown=cockpit:cockpit /app/node_modules/@prisma ./node_modules/@prisma
|
|
COPY --from=bau --chown=cockpit:cockpit /app/node_modules/prisma ./node_modules/prisma
|
|
|
|
# Betriebsskripte, die im laufenden Behaelter gebraucht werden:
|
|
# totp-geheimnis.mjs zweites Geraet fuer den Zweitfaktor einrichten
|
|
# wartungsschluessel.mjs Schluessel fuer /api/wartung ausrechnen
|
|
# schluessel-erzeugen.mjs neue Schluessel fuer die Rotation
|
|
#
|
|
# Das ganze Verzeichnis, nicht einzelne Dateien: sonst faellt beim
|
|
# naechsten Betriebsskript wieder auf, dass es fehlt - und zwar erst dann,
|
|
# wenn man es braucht. Die Entwicklungsskripte darin laufen hier mangels
|
|
# Werkzeugen nicht, kosten aber auch nur ein paar Kilobyte.
|
|
COPY --from=bau --chown=cockpit:cockpit /app/scripts ./scripts
|
|
|
|
# Ablage fuer den Dateitreiber, falls kein Objektspeicher benutzt wird.
|
|
RUN mkdir -p /app/daten/dokumente && chown -R cockpit:cockpit /app/daten
|
|
|
|
USER cockpit
|
|
EXPOSE 3000
|
|
|
|
# Migrationen laufen beim Start, danach die Anwendung. Bewusst hier und
|
|
# nicht in einem eigenen Behaelter: so kann die Datenbank nie hinter dem
|
|
# Programmstand zurueckbleiben.
|
|
CMD ["sh", "-c", "node node_modules/prisma/build/index.js migrate deploy && node server.js"]
|