Docker-Setup: App-Image (standalone), PostgreSQL-Dienst mit Auto-Import, Dev-Profil

This commit is contained in:
2026-07-17 18:26:36 +02:00
parent 7cac8cd4fc
commit 8dd6ba236e
5 changed files with 149 additions and 7 deletions
+11
View File
@@ -0,0 +1,11 @@
node_modules
.next
.git
.claude
.env*
!.env.example
ZUGANGSDATEN.md
supabase/local
Dockerfile
docker-compose.yml
README.md
+41
View File
@@ -0,0 +1,41 @@
# =============================================================
# Next.js-App als eigenständiges Produktions-Image (Multi-Stage)
# Build: docker compose --env-file .env.local build
# =============================================================
# ---------- Abhängigkeiten ----------
FROM node:24-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
# ---------- Build ----------
FROM node:24-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# NEXT_PUBLIC_*-Variablen werden zur Build-Zeit ins Client-Bundle eingebacken
ARG NEXT_PUBLIC_SUPABASE_URL
ARG NEXT_PUBLIC_SUPABASE_ANON_KEY
ENV NEXT_PUBLIC_SUPABASE_URL=$NEXT_PUBLIC_SUPABASE_URL
ENV NEXT_PUBLIC_SUPABASE_ANON_KEY=$NEXT_PUBLIC_SUPABASE_ANON_KEY
RUN npm run build
# ---------- Runtime ----------
FROM node:24-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV PORT=3000
ENV HOSTNAME=0.0.0.0
RUN addgroup -S nodejs && adduser -S nextjs -G nodejs
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
CMD ["node", "server.js"]
+32 -7
View File
@@ -38,14 +38,24 @@ scripts/ Hilfsskripte (DB-Migration, lokaler Sync)
## Entwicklung
Voraussetzung in beiden Varianten: `.env.local` mit den Werten aus
`.env.example` (liegt lokal bereits vor und ist per `.gitignore` vom
Repo ausgeschlossen).
**Variante A – Docker (nichts vorinstallieren außer Docker):**
```bash
docker compose --env-file .env.local --profile dev up dev
# http://localhost:3000 (Hot-Reload, Quellcode wird gemountet)
```
**Variante B – lokal installiertes Node.js:**
```bash
npm install
npm run dev # http://localhost:3000
```
Voraussetzung: `.env.local` mit den Werten aus `.env.example`
(liegt lokal bereits vor und ist per `.gitignore` vom Repo ausgeschlossen).
## Umgebungsvariablen (Live-Betrieb)
Beim Webserver/Hoster müssen genau diese drei Variablen hinterlegt werden
@@ -57,7 +67,16 @@ Beim Webserver/Hoster müssen genau diese drei Variablen hinterlegt werden
| `NEXT_PUBLIC_SUPABASE_ANON_KEY` | Öffentlicher anon-Key (RLS schützt die Daten) | nein |
| `SUPABASE_SERVICE_ROLE_KEY` | Service-Role-Key für die Benutzerverwaltung | **ja – niemals im Browser/Repo!** |
Build & Start auf dem Server:
Build & Start auf dem Server – **mit Docker** (empfohlen, Node.js und
PostgreSQL müssen nicht installiert sein):
```bash
docker compose --env-file .env.local up -d --build
# App: Port 3000 (hinter Reverse-Proxy mit HTTPS betreiben)
# Lokale DB-Kopie: Port 5432 (Dienst "db", optional)
```
Oder klassisch ohne Docker:
```bash
npm ci
@@ -97,9 +116,15 @@ Sicherheitsmodell (Row Level Security):
### Lokale PostgreSQL-Kopie
Auf dem Entwicklungsrechner läuft PostgreSQL 17 mit der Datenbank
`speisekarte` (Kopie von Schema + Daten aus Supabase, inkl. Minimal-Stubs
für `auth`/`storage`). Neu aufbauen bzw. aktualisieren:
Die Datenbank `speisekarte` (Kopie von Schema + Daten aus Supabase, inkl.
Minimal-Stubs für `auth`/`storage`) gibt es in zwei Varianten:
**Per Docker:** Der Dienst `db` aus `docker-compose.yml` spielt die
Skripte aus `supabase/local/` beim ersten Start automatisch ein
(PostgreSQL 17, Port 5432, Passwort über `LOCAL_PG_PASSWORD`).
**Nativ:** Auf dem Entwicklungsrechner läuft PostgreSQL 17 mit derselben
Datenbank. Neu aufbauen bzw. aktualisieren:
```powershell
$env:SUPABASE_DB_PASSWORD = "<Supabase-DB-Passwort>"
+63
View File
@@ -0,0 +1,63 @@
# =============================================================
# Speisekarte – Docker-Setup
#
# Produktion (App + lokale PostgreSQL-Kopie):
# docker compose --env-file .env.local up -d --build
#
# Entwicklung (Dev-Server mit Hot-Reload, kein lokales Node nötig):
# docker compose --env-file .env.local --profile dev up dev
#
# Die --env-file-Angabe speist NEXT_PUBLIC_* in den Build und
# SUPABASE_SERVICE_ROLE_KEY in die Laufzeit-Umgebung.
# =============================================================
services:
# ---------- Next.js-App (Produktions-Build) ----------
app:
build:
context: .
args:
NEXT_PUBLIC_SUPABASE_URL: ${NEXT_PUBLIC_SUPABASE_URL}
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${NEXT_PUBLIC_SUPABASE_ANON_KEY}
environment:
NEXT_PUBLIC_SUPABASE_URL: ${NEXT_PUBLIC_SUPABASE_URL}
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${NEXT_PUBLIC_SUPABASE_ANON_KEY}
SUPABASE_SERVICE_ROLE_KEY: ${SUPABASE_SERVICE_ROLE_KEY}
ports:
- "3000:3000"
restart: unless-stopped
# ---------- Lokale PostgreSQL-Kopie (Ablage/Auswertungen) ----------
# Beim ersten Start werden die Skripte aus supabase/local
# automatisch in alphabetischer Reihenfolge eingespielt.
db:
image: postgres:17-alpine
environment:
POSTGRES_DB: speisekarte
POSTGRES_PASSWORD: ${LOCAL_PG_PASSWORD:-speisekarte}
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
- ./supabase/local:/docker-entrypoint-initdb.d:ro
restart: unless-stopped
# ---------- Dev-Server (nur mit --profile dev) ----------
dev:
image: node:24-alpine
profiles: ["dev"]
working_dir: /app
command: sh -c "npm install && npm run dev"
environment:
NEXT_PUBLIC_SUPABASE_URL: ${NEXT_PUBLIC_SUPABASE_URL}
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${NEXT_PUBLIC_SUPABASE_ANON_KEY}
SUPABASE_SERVICE_ROLE_KEY: ${SUPABASE_SERVICE_ROLE_KEY}
ports:
- "3000:3000"
volumes:
- .:/app
- dev_node_modules:/app/node_modules
volumes:
pgdata:
dev_node_modules:
+2
View File
@@ -15,6 +15,8 @@ const securityHeaders = [
];
const nextConfig: NextConfig = {
// Für den Docker-Betrieb: minimales, eigenständiges Server-Bundle
output: "standalone",
async headers() {
return [
{