fix(docker): keine Ports auf 0.0.0.0 und ein Overlay ohne Freigaben
CI / pruefen (push) Has been cancelled
CI / pruefen (push) Has been cancelled
Der Datenbankport wurde in beiden Betriebsarten auf 0.0.0.0 gelegt, obwohl ihn nur die Entwicklung braucht: im Container spricht die Anwendung "db:5432" ueber das Compose-Netz an, und backup.sh geht ueber docker exec. Auf einem Server lauschte Postgres damit im Netz, geschuetzt allein durch das Passwort aus der .env. Die Anleitung riet zwar zu 127.0.0.1, aber als Handgriff statt als Voreinstellung -- die falsche Richtung. Datenbank und Adminer binden jetzt von Haus aus auf 127.0.0.1. Liegen mehrere Stacks auf einem Host und regelt ein gemeinsamer Reverse Proxy den Zugang, braucht Nebula gar keinen Host-Port. docker-compose.server.yml nimmt beide Freigaben zurueck und haengt die Anwendung in ein geteiltes Netz. Das braucht !reset: Compose fuehrt "ports" beim Zusammenfuehren anhaengend statt ersetzend zusammen, eine leere Liste im Override wuerde also nichts loeschen. update.sh las die Adresse aus APP_PORT und haette in diesem Modus einen Port gemeldet, den es nicht gibt. Es fragt jetzt Docker und sagt sonst, dass nur das interne Netz erreichbar ist. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+68
-10
@@ -86,19 +86,54 @@ APP_PORT=127.0.0.1:3000
|
||||
> **`APP_URL` später zu ändern** macht bestehende **Passkeys ungültig**, weil
|
||||
> sie an die rpID gebunden sind. Passwörter funktionieren weiter.
|
||||
|
||||
### Datenbankport schließen
|
||||
### Welche Ports überhaupt hinausgehen
|
||||
|
||||
`docker-compose.yml` bildet Postgres standardmäßig auf `5432` ab, damit man
|
||||
in der Entwicklung von außen drankommt. Auf einem Server hat die Datenbank
|
||||
nichts im Internet zu suchen:
|
||||
| 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 |
|
||||
|
||||
```env
|
||||
POSTGRES_PORT=127.0.0.1:5432
|
||||
**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.
|
||||
|
||||
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.
|
||||
|
||||
### 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.
|
||||
|
||||
```bash
|
||||
docker network create proxy # falls der Proxy-Stack es nicht schon anlegt
|
||||
```
|
||||
|
||||
Noch besser: die `ports:`-Zeile des `db`-Dienstes ganz entfernen. Die
|
||||
Anwendung erreicht die Datenbank über das interne Docker-Netz, nicht über
|
||||
den Host.
|
||||
```env
|
||||
# .env
|
||||
COMPOSE_FILE="docker-compose.yml:docker-compose.server.yml"
|
||||
COMPOSE_PROFILES="full"
|
||||
PROXY_NETWORK="proxy" # so heißt das Netz
|
||||
PROXY_ALIAS="nebula" # so findet der Proxy die Anwendung
|
||||
```
|
||||
|
||||
Compose liest beides aus der `.env`. Danach genügt überall — auch in
|
||||
`scripts/update.sh` — ein schlichtes `docker compose up -d`. Im Proxy zeigt
|
||||
das Ziel dann nicht mehr auf `127.0.0.1:3000`, sondern auf **`nebula:3000`**;
|
||||
Schritt 6 zeigt beide Schreibweisen.
|
||||
|
||||
> Ohne die Datei würde ein Override die Portlisten **zusammenhängen** statt
|
||||
> sie zu ersetzen — Compose führt `ports` anfügend zusammen. Das `!reset`
|
||||
> darin ist genau dafür da und braucht Compose 2.24 oder neuer.
|
||||
>
|
||||
> Das Trennzeichen in `COMPOSE_FILE` ist unter Linux der Doppelpunkt, unter
|
||||
> Windows das Semikolon.
|
||||
|
||||
## 4 · Starten
|
||||
|
||||
@@ -114,6 +149,13 @@ docker compose --profile full logs -f app # mitlesen, Strg+C beendet nur das
|
||||
curl -s localhost:3000/api/health # {"status":"ok","database":"up",…}
|
||||
```
|
||||
|
||||
Ohne veröffentlichten Port geht die Frage an den Container statt an den Host
|
||||
— das Abbild bringt einen `HEALTHCHECK` mit:
|
||||
|
||||
```bash
|
||||
docker inspect --format '{{.State.Health.Status}}' nebula-app # healthy
|
||||
```
|
||||
|
||||
## 5 · Ersten Zugang anlegen
|
||||
|
||||
Ruf `https://nebula.deine-domain.de/setup` auf (nach Schritt 6) oder
|
||||
@@ -151,6 +193,16 @@ sudo systemctl reload caddy
|
||||
Das genügt. Caddy setzt `X-Forwarded-*` von selbst, holt das Zertifikat bei
|
||||
Let's Encrypt und leitet `http` auf `https` um.
|
||||
|
||||
Läuft der Proxy selbst als Container im geteilten Netz (die Variante ohne
|
||||
veröffentlichte Ports), lautet das Ziel stattdessen `nebula:3000` —
|
||||
Docker löst den Alias auf:
|
||||
|
||||
```caddyfile
|
||||
nebula.deine-domain.de {
|
||||
reverse_proxy nebula:3000
|
||||
}
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Dasselbe mit nginx</summary>
|
||||
|
||||
@@ -189,7 +241,13 @@ sudo ufw enable
|
||||
```
|
||||
|
||||
Port 3000 und 5432 bleiben **zu**. Beide sind nach Schritt 3 ohnehin nur an
|
||||
`127.0.0.1` gebunden; die Firewall ist der zweite Riegel.
|
||||
`127.0.0.1` gebunden — oder gar nicht erst veröffentlicht; die Firewall ist
|
||||
der zweite Riegel.
|
||||
|
||||
> 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
|
||||
> `ufw` sie zu melden scheint. Genau deshalb wird hier an `127.0.0.1`
|
||||
> gebunden, statt sich auf die Firewall zu verlassen.
|
||||
|
||||
## 8 · Sicherungen automatisieren
|
||||
|
||||
|
||||
Reference in New Issue
Block a user