fix(docker): die Datenbank veroeffentlicht ueberhaupt keinen Host-Port mehr
CI / pruefen (push) Has been cancelled
CI / pruefen (push) Has been cancelled
Der letzte Anlauf hat das Problem nicht geloest. Die Freigabe stand weiter in der Basisdatei, nur mit anderem Vorgabewert -- und Vorgabewerte greifen nicht, wo die Variable schon gesetzt ist: in jeder .env, die aus der bisherigen .env.example entstanden ist, steht POSTGRES_PORT="5432". Postgres band also unveraendert auf 0.0.0.0 und kollidierte mit anderen Stacks auf demselben Host; der Container kam gar nicht erst hoch. Das Overlay half nicht, weil es erst greift, wenn man es dazunimmt. Jetzt hat der db-Dienst keinen ports-Block mehr. Gebraucht wird er nur, wenn die Anwendung ausserhalb des Containers laeuft, und dafuer gibt es docker-compose.dev.yml (npm run docker:db). Damit ist der sichere Fall die Vorgabe und der Sonderfall die Ausnahme, nicht umgekehrt. Der App-Port bindet aus demselben Grund auf 127.0.0.1: Docker traegt seine Freigaben direkt in iptables ein und umgeht dabei ufw. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+9
-6
@@ -23,11 +23,13 @@ APP_URL="http://localhost:3000"
|
||||
|
||||
# Port innerhalb des Containers bzw. im Standalone-Betrieb
|
||||
PORT="3000"
|
||||
# Host-Port-Mapping fuer den App-Container (--profile full)
|
||||
APP_PORT="3000"
|
||||
# Host-Port-Mapping fuer den App-Container (--profile full). Nur auf dem
|
||||
# Loopback – nach draussen geht es ueber einen Reverse Proxy. Soll die
|
||||
# Instanz im LAN erreichbar sein, hier "3000" eintragen.
|
||||
APP_PORT="127.0.0.1:3000"
|
||||
|
||||
# ── Datenbank ────────────────────────────────────────────────
|
||||
# Standalone-Betrieb: App laeuft lokal, Postgres via "docker compose up -d db"
|
||||
# Standalone-Betrieb: App laeuft lokal, Postgres via "npm run docker:db"
|
||||
# oder als nativ installierter Dienst.
|
||||
DATABASE_URL="postgresql://nebula:nebula@localhost:5432/nebula?schema=public"
|
||||
|
||||
@@ -38,9 +40,10 @@ DATABASE_URL="postgresql://nebula:nebula@localhost:5432/nebula?schema=public"
|
||||
POSTGRES_USER="nebula"
|
||||
POSTGRES_PASSWORD="nebula"
|
||||
POSTGRES_DB="nebula"
|
||||
# Host-Port, unter dem die Datenbank erreichbar ist. Nur die Entwicklung
|
||||
# braucht ihn: im Container spricht die Anwendung "db:5432" an. Deshalb an
|
||||
# 127.0.0.1 gebunden, damit er nicht im Netz steht.
|
||||
# Host-Port der Datenbank. Wirkt NUR zusammen mit docker-compose.dev.yml
|
||||
# (npm run docker:db) – die Basisdatei veroeffentlicht keinen DB-Port, weil
|
||||
# die Anwendung im Container "db:5432" anspricht und nichts davon nach
|
||||
# aussen muss. Auf einem Server bleibt dieser Wert also folgenlos.
|
||||
POSTGRES_PORT="127.0.0.1:5432"
|
||||
# Host-Port fuer Adminer (--profile tools)
|
||||
ADMINER_PORT="127.0.0.1:8080"
|
||||
|
||||
@@ -9,7 +9,8 @@ Betrieb: [README.md](README.md) · Server: [DEPLOYMENT.md](DEPLOYMENT.md)
|
||||
## Womit man arbeitet
|
||||
|
||||
```bash
|
||||
docker compose up -d db # Postgres, muss laufen
|
||||
npm run docker:db # Postgres, muss laufen (mit dem dev-Overlay,
|
||||
# sonst hat die DB keinen Host-Port)
|
||||
npm run dev # Entwicklung
|
||||
npm test # Unit-Tests (Vitest, ohne DB)
|
||||
npx tsc --noEmit # Typprüfung
|
||||
|
||||
+27
-22
@@ -62,7 +62,7 @@ chmod 600 .env
|
||||
openssl rand -base64 32 # den Wert als APP_SECRET eintragen
|
||||
```
|
||||
|
||||
Dann die `.env` öffnen und mindestens diese vier Werte anpassen:
|
||||
Dann die `.env` öffnen und mindestens diese drei Werte anpassen:
|
||||
|
||||
```env
|
||||
# Die Adresse, unter der du Nebula im Browser aufrufst.
|
||||
@@ -74,11 +74,11 @@ APP_SECRET="…dein-langer-zufallswert…"
|
||||
|
||||
# Das Datenbankpasswort. Die Voreinstellung „nebula" ist für Entwicklung.
|
||||
POSTGRES_PASSWORD="…noch-ein-langer-zufallswert…"
|
||||
|
||||
# Nur lokal lauschen — nach außen geht es über den Reverse Proxy (Schritt 6).
|
||||
APP_PORT=127.0.0.1:3000
|
||||
```
|
||||
|
||||
Die Ports müssen nicht angefasst werden: `APP_PORT` steht schon auf
|
||||
`127.0.0.1:3000`, und die Datenbank veröffentlicht gar nichts.
|
||||
|
||||
> **`APP_SECRET` später zu ändern** macht gespeicherte Git-Tokens unlesbar.
|
||||
> Sie müssen dann neu hinterlegt werden. Konten, Passwörter und Passkeys
|
||||
> bleiben unberührt.
|
||||
@@ -88,28 +88,34 @@ APP_PORT=127.0.0.1:3000
|
||||
|
||||
### Welche Ports überhaupt hinausgehen
|
||||
|
||||
| Container | Host-Port | Wann | Wird gebraucht? |
|
||||
| --- | --- | --- | --- |
|
||||
| `nebula-app` | `APP_PORT` → 3000 | `--profile full` | ja — das ist die Anwendung |
|
||||
| `nebula-db` | `POSTGRES_PORT` → 5432 | immer | **nein** |
|
||||
| `nebula-adminer` | `ADMINER_PORT` → 8080 | nur `--profile tools` | nein |
|
||||
Nach einer regulären Installation ist es **genau einer**:
|
||||
|
||||
**Der Datenbankport muss nicht nach außen.** Im Vollbetrieb spricht die
|
||||
Anwendung Postgres über das interne Docker-Netz als `db:5432` an — die
|
||||
`DATABASE_URL` setzt Compose selbst. Auch `scripts/backup.sh` und
|
||||
`restore.sh` gehen über `docker exec`, nicht über den Host. Die Freigabe
|
||||
existiert allein für die Entwicklung, wo `npm run dev` auf dem Host läuft.
|
||||
| Container | Host-Port | Wann |
|
||||
| --- | --- | --- |
|
||||
| `nebula-app` | `APP_PORT`, Vorgabe `127.0.0.1:3000` | `--profile full` |
|
||||
| `nebula-db` | — | **nie** |
|
||||
| `nebula-adminer` | `ADMINER_PORT`, Vorgabe `127.0.0.1:8080` | nur `--profile tools` |
|
||||
|
||||
Sie ist deshalb auf `127.0.0.1` gebunden und damit vom Netz aus nicht
|
||||
erreichbar. Auf einem Server kann sie ganz weg — siehe den nächsten
|
||||
Abschnitt.
|
||||
**Die Datenbank veröffentlicht nichts.** Im Vollbetrieb spricht die Anwendung
|
||||
Postgres über das interne Docker-Netz als `db:5432` an — die `DATABASE_URL`
|
||||
setzt Compose selbst. Auch `scripts/backup.sh` und `restore.sh` gehen über
|
||||
`docker exec`, nicht über den Host. Ein Host-Port wäre nur eine zusätzliche
|
||||
Angriffsfläche und würde mit anderen Postgres-Containern auf demselben Host
|
||||
um den Port streiten.
|
||||
|
||||
Wer die Datenbank beim Entwickeln doch vom Host aus braucht — `npm run dev`
|
||||
läuft ja außerhalb des Containers — nimmt `docker-compose.dev.yml` dazu
|
||||
(`npm run docker:db`). Auf einem Server hat diese Datei nichts zu suchen.
|
||||
|
||||
Auch der Port der Anwendung liegt auf `127.0.0.1`: nach draußen geht es über
|
||||
den Reverse Proxy aus Schritt 6.
|
||||
|
||||
### Variante: gar keinen Port veröffentlichen
|
||||
|
||||
Liegen mehrere Stacks auf demselben Docker-Host und regelt ein gemeinsamer
|
||||
Reverse Proxy den Zugang, braucht Nebula überhaupt keinen Host-Port. Dafür
|
||||
gibt es **`docker-compose.server.yml`**: es nimmt beide Freigaben zurück und
|
||||
hängt die Anwendung zusätzlich in ein geteiltes Netz.
|
||||
gibt es **`docker-compose.server.yml`**: es nimmt die letzte verbliebene
|
||||
Freigabe zurück und hängt die Anwendung in ein geteiltes Netz.
|
||||
|
||||
```bash
|
||||
docker network create proxy # falls der Proxy-Stack es nicht schon anlegt
|
||||
@@ -240,9 +246,8 @@ sudo ufw allow 80,443/tcp
|
||||
sudo ufw enable
|
||||
```
|
||||
|
||||
Port 3000 und 5432 bleiben **zu**. Beide sind nach Schritt 3 ohnehin nur an
|
||||
`127.0.0.1` gebunden — oder gar nicht erst veröffentlicht; die Firewall ist
|
||||
der zweite Riegel.
|
||||
Port 3000 bleibt **zu**, 5432 wird ohnehin nie veröffentlicht. Die Firewall
|
||||
ist hier der zweite Riegel, nicht der erste.
|
||||
|
||||
> Docker schreibt seine Portfreigaben direkt in `iptables` und geht dabei an
|
||||
> `ufw` **vorbei**. Eine Freigabe auf `0.0.0.0` steht also im Netz, auch wenn
|
||||
|
||||
@@ -52,7 +52,7 @@ node scripts/setup.mjs # legt .env an und erzeugt ein zufälliges APP_SECRE
|
||||
Die App läuft nativ auf dem Rechner, nur PostgreSQL kommt aus dem Container:
|
||||
|
||||
```bash
|
||||
docker compose up -d db # Postgres 17 auf localhost:5432
|
||||
npm run docker:db # Postgres 17 auf 127.0.0.1:5432
|
||||
npm install
|
||||
npm run db:migrate # Schema anlegen
|
||||
npm run db:seed # optional: drei Beispielprojekte
|
||||
@@ -120,9 +120,9 @@ Alle Variablen sind in [`.env.example`](.env.example) dokumentiert.
|
||||
| `APP_SECRET` | Schlüssel für die Token-Verschlüsselung (AES-256-GCM) | — **unbedingt setzen** |
|
||||
| `SESSION_TTL_DAYS` | Lebensdauer einer Anmeldung in Tagen | `30` |
|
||||
| `PORT` | Port der Anwendung | `3000` |
|
||||
| `APP_PORT` | Host-Port-Mapping des App-Containers | `3000` |
|
||||
| `APP_PORT` | Host-Port-Mapping des App-Containers | `127.0.0.1:3000` |
|
||||
| `POSTGRES_USER` / `POSTGRES_PASSWORD` / `POSTGRES_DB` | Zugangsdaten des DB-Containers | `nebula` |
|
||||
| `POSTGRES_PORT` | Host-Port der Datenbank — nur für die Entwicklung, im Container läuft es über `db:5432` | `127.0.0.1:5432` |
|
||||
| `POSTGRES_PORT` | Host-Port der Datenbank — wirkt nur mit `docker-compose.dev.yml`, sonst hat die DB keinen | `127.0.0.1:5432` |
|
||||
| `ADMINER_PORT` | Host-Port von Adminer (`--profile tools`) | `127.0.0.1:8080` |
|
||||
| `GIT_API_TIMEOUT_MS` | Timeout für Git-API-Aufrufe | `15000` |
|
||||
| `GIT_ALLOW_LOOPBACK` | Git-Instanz auf demselben Rechner erlauben | `false` |
|
||||
@@ -307,7 +307,7 @@ nebula/
|
||||
| `npm test` | Unit-Tests (Vitest, ohne Datenbank) |
|
||||
| `npm run test:e2e` | Ende-zu-Ende-Tests (Playwright, baut vorher) |
|
||||
| `npm run test:all` | Beides nacheinander |
|
||||
| `npm run docker:db` | Nur die Datenbank starten |
|
||||
| `npm run docker:db` | Nur die Datenbank starten, mit Host-Port für `npm run dev` |
|
||||
| `npm run docker:up` / `docker:down` | Kompletten Stack starten / stoppen |
|
||||
| `npm run docker:tools` | Adminer auf `http://localhost:8080` |
|
||||
|
||||
@@ -416,7 +416,7 @@ Grenzen, die du kennen solltest:
|
||||
|
||||
| Symptom | Ursache / Lösung |
|
||||
| --- | --- |
|
||||
| `Can't reach database server` | Läuft `docker compose up -d db`? Stimmt `DATABASE_URL`? |
|
||||
| `Can't reach database server` | Läuft `npm run docker:db`? Ein blosses `docker compose up -d db` startet die DB **ohne Host-Port** — dann ist sie von `npm run dev` aus nicht erreichbar. Stimmt `DATABASE_URL`? |
|
||||
| `The table ... does not exist` | Migrationen fehlen: `npm run db:migrate` |
|
||||
| Sync meldet `401` | Token abgelaufen oder falsche Scopes — unter Git-Verbindungen neu setzen |
|
||||
| Sync meldet `404` | Owner/Repo prüfen; bei GitLab gehört die volle Gruppenkette in „Owner" |
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# Overlay fuer die Entwicklung: macht die Datenbank auf dem Host erreichbar.
|
||||
#
|
||||
# Gebraucht wird das nur, wenn die Anwendung ausserhalb des Containers
|
||||
# laeuft – "npm run dev" verbindet sich dann ueber localhost:5432. Im
|
||||
# Vollbetrieb spricht die Anwendung "db:5432" im Docker-Netz an und braucht
|
||||
# diese Datei nicht.
|
||||
#
|
||||
# Aufruf:
|
||||
# docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d db
|
||||
# npm run dev
|
||||
#
|
||||
# Kuerzer: npm run docker:db
|
||||
#
|
||||
# Gebunden wird auf 127.0.0.1, nicht auf 0.0.0.0. Docker traegt Freigaben
|
||||
# direkt in iptables ein und umgeht dabei ufw – eine offene Bindung stuende
|
||||
# also auch bei aktiver Firewall im Netz.
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
|
||||
services:
|
||||
db:
|
||||
ports:
|
||||
- "${POSTGRES_PORT:-127.0.0.1:5432}:5432"
|
||||
@@ -1,10 +1,11 @@
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# Overlay fuer den Serverbetrieb: kein Port geht nach aussen.
|
||||
# Overlay fuer den Serverbetrieb: kein einziger Port geht zum Host.
|
||||
#
|
||||
# Gedacht fuer einen Docker-Host, auf dem mehrere Stacks liegen und ein
|
||||
# gemeinsamer Reverse Proxy die einzige Tuer nach draussen ist. Weder die
|
||||
# Datenbank noch die Anwendung veroeffentlichen dann einen Host-Port; der
|
||||
# Proxy erreicht Nebula ueber ein geteiltes Docker-Netz.
|
||||
# gemeinsamer Reverse Proxy die einzige Tuer nach draussen ist. Die
|
||||
# Datenbank veroeffentlicht ohnehin nichts; diese Datei nimmt zusaetzlich
|
||||
# die Freigabe der Anwendung zurueck und haengt sie in ein geteiltes Netz,
|
||||
# ueber das der Proxy sie erreicht.
|
||||
#
|
||||
# Aufruf:
|
||||
# docker compose -f docker-compose.yml -f docker-compose.server.yml \
|
||||
@@ -14,6 +15,7 @@
|
||||
# COMPOSE_FILE=docker-compose.yml:docker-compose.server.yml
|
||||
# COMPOSE_PROFILES=full
|
||||
# Danach genuegt ueberall "docker compose up -d" – auch in update.sh.
|
||||
# (Trennzeichen: Doppelpunkt unter Linux, Semikolon unter Windows.)
|
||||
#
|
||||
# Das Netz muss es vorher geben (der Proxy-Stack legt es ueblicherweise an):
|
||||
# docker network create proxy
|
||||
@@ -22,13 +24,11 @@
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
|
||||
services:
|
||||
db:
|
||||
app:
|
||||
# !reset loescht die Portfreigabe aus der Basisdatei. Ohne dieses Tag
|
||||
# wuerden die Listen zusammengefuegt statt ersetzt – Compose behandelt
|
||||
# "ports" beim Zusammenfuehren als anzuhaengende Liste.
|
||||
ports: !reset []
|
||||
|
||||
app:
|
||||
# "ports" beim Zusammenfuehren als anzuhaengende Liste. Braucht
|
||||
# Compose 2.24 oder neuer.
|
||||
ports: !reset []
|
||||
networks:
|
||||
# Das stackeigene Netz: darueber spricht die Anwendung mit der Datenbank.
|
||||
|
||||
+20
-12
@@ -1,14 +1,20 @@
|
||||
name: nebula
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# Zwei Betriebsarten aus einer Datei:
|
||||
# Diese Datei veroeffentlicht nur einen einzigen Port, und den auf dem
|
||||
# Loopback: den der Anwendung. Die Datenbank bleibt im Docker-Netz.
|
||||
#
|
||||
# 1) Standalone-Entwicklung – nur die Datenbank im Container:
|
||||
# docker compose up -d db
|
||||
# 1) Alles im Container (Server wie Entwicklung):
|
||||
# docker compose --profile full up -d --build
|
||||
#
|
||||
# 2) Standalone-Entwicklung – Datenbank im Container, App auf dem Host.
|
||||
# Dafuer muss Postgres auf dem Host erreichbar sein, also mit dem
|
||||
# Entwicklungs-Overlay (oder kurz: npm run docker:db):
|
||||
# docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d db
|
||||
# npm run dev
|
||||
#
|
||||
# 2) Alles im Container:
|
||||
# docker compose --profile full up -d --build
|
||||
# 3) Server ohne jede Portfreigabe, hinter einem Reverse Proxy im
|
||||
# gemeinsamen Docker-Netz: siehe docker-compose.server.yml
|
||||
#
|
||||
# Optionales DB-Webinterface:
|
||||
# docker compose --profile tools up -d adminer → http://localhost:8080
|
||||
@@ -25,12 +31,10 @@ services:
|
||||
POSTGRES_DB: ${POSTGRES_DB:-nebula}
|
||||
# Deterministische Sortierung unabhaengig vom Host-Locale
|
||||
POSTGRES_INITDB_ARGS: "--encoding=UTF8"
|
||||
ports:
|
||||
# Nur fuer die Entwicklung – die Anwendung erreicht die Datenbank im
|
||||
# Container ueber "db:5432", nicht ueber den Host. Deshalb an 127.0.0.1
|
||||
# gebunden. Im Serverbetrieb faellt die Freigabe ganz weg, siehe
|
||||
# docker-compose.server.yml.
|
||||
- "${POSTGRES_PORT:-127.0.0.1:5432}:5432"
|
||||
# Absichtlich keine Portfreigabe: die Anwendung erreicht die Datenbank im
|
||||
# Container ueber "db:5432", und backup.sh geht ueber "docker exec". Nach
|
||||
# aussen muss hier nichts. Wer die Datenbank vom Host aus braucht – fuer
|
||||
# "npm run dev" oder psql – nimmt docker-compose.dev.yml dazu.
|
||||
volumes:
|
||||
- nebula-db-data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
@@ -77,7 +81,11 @@ services:
|
||||
PORT: 3000
|
||||
HOSTNAME: 0.0.0.0
|
||||
ports:
|
||||
- "${APP_PORT:-3000}:3000"
|
||||
# Nur auf dem Loopback: nach draussen kommt man ueber den Reverse Proxy.
|
||||
# Docker schreibt seine Freigaben an ufw vorbei direkt in iptables – eine
|
||||
# Bindung auf 0.0.0.0 stuende also im Netz, auch bei aktiver Firewall.
|
||||
# Ganz ohne Host-Port: docker-compose.server.yml.
|
||||
- "${APP_PORT:-127.0.0.1:3000}:3000"
|
||||
|
||||
adminer:
|
||||
profiles: ["tools"]
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
"db:studio": "prisma studio",
|
||||
"db:seed": "prisma db seed",
|
||||
"db:reset": "prisma migrate reset",
|
||||
"docker:db": "docker compose up -d db",
|
||||
"docker:db": "docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d db",
|
||||
"docker:db:down": "docker compose stop db",
|
||||
"docker:up": "docker compose --profile full up -d --build",
|
||||
"docker:down": "docker compose --profile full down",
|
||||
|
||||
Reference in New Issue
Block a user