Make the build fit Vercel without breaking the container

Two settings were wrong for a platform build.

output: "standalone" tells Next.js to emit a self-contained server, which is
what the Dockerfile copies in — and what Vercel neither needs nor expects,
since it builds and packages the app itself. It is now conditional on the
VERCEL variable, which every build there sets, so each path gets what it
wants. Verified both ways: with VERCEL=1 no standalone directory appears,
without it one does.

/api/import declared maxDuration = 120. The free tier caps at 60 and refuses
anything higher, so the deployment would have failed on a value chosen for a
self-hosted server. Lowered, with the reason and the Pro ceiling written
next to it.

DEPLOYMENT.md now covers both paths, and says plainly that the repository
cannot be connected: git.elycon.solutions is self-hosted, and Vercel's git
integration only speaks GitHub, GitLab and Bitbucket. Deploying from the
workstation with the CLI works with any repository and is the shorter road;
mirroring to GitHub is written down as the alternative, with its cost — two
remotes to keep in step.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-06 15:17:24 +02:00
parent 27cfd6431f
commit ecbda3f3a5
3 changed files with 78 additions and 7 deletions

View File

@@ -1,8 +1,71 @@
# Deployment mit Docker
# Deployment
Dieser Guide beschreibt, wie die App (bisher auf Vercel deployed, siehe
`vercel.json`) stattdessen als Docker-Container auf einem beliebigen Server
läuft.
Zwei Wege, beide unterstützt. Das Abbild ist umgebungsneutral — es gibt keine
Werte mehr, die beim Bauen eingebacken werden —, ein Wechsel ist also
jederzeit möglich.
| | passt, wenn |
|---|---|
| [Vercel](#vercel) | ihr nichts betreiben wollt; schnellster Weg |
| [Docker](#deployment-mit-docker) | es in eure eigene Infrastruktur soll |
**In beiden Fällen gleich:** die Umgebungsvariablen aus [Abschnitt 1](#1-env-anlegen),
die Umleitungs-URI in der Entra-Registrierung, und dass eine neue Person nach
ihrer ersten Anmeldung eine `profiles`-Zeile braucht (siehe
[docs/entra-sso.md](docs/entra-sso.md)).
## Vercel
Das Repository liegt auf `git.elycon.solutions` — einem selbst betriebenen
Git. **Vercels Git-Anbindung kann nur GitHub, GitLab und Bitbucket**, dieses
Repository lässt sich dort also nicht verknüpfen. Zwei Möglichkeiten:
### a) Von der Arbeitsstation ausrollen (ohne GitHub)
```bash
npx vercel login
npx vercel link
npx vercel --prod
```
Funktioniert mit jedem Repository. Der Preis: kein automatisches Ausrollen
bei einem Push — jede Veröffentlichung ist ein bewusster Befehl. Für zwei
Personen ist das eher Vorteil als Nachteil.
### b) Zusätzlich nach GitHub spiegeln
```bash
git remote add github git@github.com:<konto>/alpenwerk-hr.git
git push github feat/sap-om-org-model
```
Danach das GitHub-Repository in Vercel verbinden. Ab dann rollt jeder Push
aus. Zwei Fernziele bedeuten aber auch: beide müssen gepflegt werden.
### Danach
1. **Umgebungsvariablen** im Vercel-Projekt setzen (Settings → Environment
Variables), dieselben wie in [Abschnitt 1](#1-env-anlegen). `AUTH_URL` ist
nicht nötig, Vercel setzt den Host selbst.
2. **Umleitungs-URI** in der Entra-Registrierung ergänzen:
`https://<projekt>.vercel.app/api/auth/callback/microsoft-entra-id`
3. Der nächtliche Lauf ist über `vercel.json` bereits eingerichtet.
Zwei Eigenheiten der Plattform, die im Code berücksichtigt sind:
`output: "standalone"` entfällt dort automatisch (Vercel baut selbst), und
`/api/import` ist auf 60 Sekunden begrenzt — die Obergrenze des kostenlosen
Tarifs. Im Pro-Tarif liessen sich 300 setzen, falls eine Importdatei mit
vielen tausend Zeilen ansteht.
Der Verbindungspool passt zu serverlosen Aufrufen, **weil** `DATABASE_URL`
auf den Transaktions-Modus zeigt (Port 6543). Mit dem Sitzungs-Modus wären
die 15 Verbindungen des Tarifs nach wenigen gleichzeitigen Aufrufen
verbraucht.
## Deployment mit Docker
Dieser Guide beschreibt, wie die App stattdessen als Docker-Container auf
einem beliebigen Server läuft.
## Was wird containerisiert – und was nicht