Baustein 1: Grundgeruest, Datenbank, Anmeldung, zwei Rollen

Legt das Fundament der Lern-Bar an:

- Next.js 15 (App Router), React 19, TypeScript, ESLint, Vitest
- SQLite ueber Drizzle hinter einer Repository-Schicht
- Eigener Migrationslauf mit Pruefsummen, beim Start angewendet
- Argon2id, serverseitige Sitzungen, HttpOnly-Cookie, SameSite=Lax
- Rollen Ausbilder und Azubi, Rechteregeln als reine Funktionen
- Verwaltung: Azubikonto und Ausbildung anlegen, Passwort, Sperren
- Gestaltung Petrol/Bernstein, helle und dunkle Darstellung
- Dockerfile, docker-compose, Lebenszeichen, update.sh mit Rueckfall
- Sicherung und Wiederherstellung als Shell-Skripte
- 29 Tests fuer Rechte, Zeitrechnung und Migrationslauf

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Florian Wilde
2026-09-10 00:52:44 +02:00
co-authored by Claude Opus 5
commit e856349cd4
51 changed files with 11883 additions and 0 deletions
+68
View File
@@ -0,0 +1,68 @@
# syntax=docker/dockerfile:1
# ---------------------------------------------------------------------------
# Lern-Bar – mehrstufiges Abbild
#
# Debian-slim statt Alpine, weil better-sqlite3 und @node-rs/argon2 dort
# fertige Binärdateien mitbringen und nichts übersetzt werden muss.
# ---------------------------------------------------------------------------
ARG NODE_VERSION=22-bookworm-slim
# --- Abhängigkeiten -------------------------------------------------------
FROM node:${NODE_VERSION} AS abhaengigkeiten
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends python3 build-essential \
&& rm -rf /var/lib/apt/lists/*
COPY package.json package-lock.json ./
RUN npm ci --ignore-scripts=false --no-audit --no-fund
# --- Übersetzen -----------------------------------------------------------
FROM node:${NODE_VERSION} AS bau
WORKDIR /app
ENV NEXT_TELEMETRY_DISABLED=1
COPY --from=abhaengigkeiten /app/node_modules ./node_modules
COPY . .
RUN npm run build
# --- Laufzeit -------------------------------------------------------------
FROM node:${NODE_VERSION} AS laufzeit
WORKDIR /app
ENV NODE_ENV=production \
NEXT_TELEMETRY_DISABLED=1 \
TZ=Europe/Berlin \
PORT=3000 \
HOSTNAME=0.0.0.0 \
LERNBAR_DATEN=/daten \
LERNBAR_INHALTE=/app/content \
LERNBAR_MIGRATIONEN=/app/migrationen
# tini fängt Signale ab, damit `docker stop` sauber beendet.
RUN apt-get update && apt-get install -y --no-install-recommends tini ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# Standalone-Ausgabe von Next.js bringt genau die nötigen node_modules mit.
COPY --from=bau /app/.next/standalone ./
COPY --from=bau /app/.next/static ./.next/static
COPY --from=bau /app/public ./public
# Inhalte und Migrationen liegen als Dateien im Abbild.
COPY --from=bau /app/content ./content
COPY --from=bau /app/src/lib/db/migrationen ./migrationen
# Werkzeuge für Sicherung und Wiederherstellung im Container.
COPY --from=bau /app/scripts/im-container ./werkzeuge
RUN chmod +x ./werkzeuge/*.sh
RUN mkdir -p /daten && chown -R node:node /daten /app
USER node
VOLUME ["/daten"]
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
CMD node -e "fetch('http://127.0.0.1:'+(process.env.PORT||3000)+'/api/gesundheit').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
ENTRYPOINT ["/usr/bin/tini", "--"]
CMD ["node", "server.js"]