8.0 KiB
Produktion mit Dokploy und Registry-Images
docker-compose.production.yml ist eine eigenständige Compose-Datei. Sie benötigt keine andere Compose-Datei und keinen lokalen Build. App, Migration und Worker verwenden dieselbe explizite Release-Version. Ein erfolgreicher Registry-Publish beider Images ist Voraussetzung; ein Git-Tag allein bedeutet noch nicht, dass die Images verfuegbar sind. Siehe REGISTRY.md.
Konfiguration
Variante ohne Traefik
docker-compose.production.direct.yml ist ebenfalls eigenständig und benötigt weder Dokploy noch ein externes Proxy-Netz. Sie veröffentlicht die App standardmäßig auf 127.0.0.1:3000 des Docker-Hosts. Die übrigen Dienste, Daten-Volumes und Migrationen entsprechen der Traefik-Variante. Nur eine der beiden Compose-Dateien verwenden.
APP_PORT bestimmt den Host-Port. APP_BIND_ADDRESS=127.0.0.1 eignet sich für einen auf demselben Host laufenden HTTPS-Proxy, beispielsweise Nginx oder Caddy. Bei einem separaten vorgeschalteten Proxy die erreichbare private Host-IP einstellen und den Port entsprechend auf diesen Proxy begrenzen. 0.0.0.0 bindet an alle IPv4-Schnittstellen. TRAEFIK_NETWORK wird in dieser Variante nicht verwendet.
Die App selbst stellt HTTP bereit. Die öffentliche Produktionsadresse in NEXTAUTH_URL bleibt HTTPS; TLS muss deshalb ein vorhandener HTTPS-Proxy oder Load Balancer übernehmen. Die Datei stellt keinen eigenen TLS-Dienst bereit und deaktiviert die HTTPS-Prüfung der Anwendung nicht. Eine Nginx-Vorlage liegt unter deploy/nginx.conf.example.
Für alle nachfolgenden CLI-Schritte und die Datenübernahme diese Funktion verwenden:
dc() { docker compose --env-file .env.production -p taskmanager-next -f docker-compose.production.direct.yml "$@"; }
dc config --quiet
Den Projektnamen konsistent auf den Namen der vorbereiteten Zielinstallation setzen. Die spätere Funktionsdefinition für die Dokploy-Variante überspringen. Nach Restore, Migration und Start lässt sich die App lokal prüfen:
curl --fail http://127.0.0.1:3000/api/health
Bei abweichendem APP_PORT oder APP_BIND_ADDRESS die Prüfadresse entsprechend anpassen.
Variante mit Dokploy/Traefik
In Dokploy ein Compose-Projekt mit docker-compose.production.yml konfigurieren. Die Werte aus .env.production.example in die Compose-Umgebung übernehmen. Alternativ auf dem Server:
cp .env.production.example .env.production
chmod 600 .env.production
openssl rand -hex 32 # NEXTAUTH_SECRET
openssl rand -hex 24 # Passwort für eine neue Ziel-Datenbank
Pflichtwerte:
| Variable | Wert |
|---|---|
TASKMANAGER_VERSION |
Tatsächlich veröffentlichte Version, z.B. 1.0.1 |
POSTGRES_PASSWORD |
Passwort der Ziel-Datenbank |
DATABASE_URL |
postgresql://taskmanager:PASSWORT@db:5432/taskmanager (Sonderzeichen URL-kodieren) |
NEXTAUTH_URL |
Öffentliche HTTPS-Adresse der Aufgabenverwaltung |
NEXTAUTH_SECRET |
Zufälliges Secret mit mindestens 32 Zeichen |
POSTGRES_VOLUME |
Exakter Name des vorbereiteten Ziel-Volumes für PostgreSQL 16 |
UPLOADS_VOLUME |
Exakter Name des Ziel-Volumes mit wiederhergestellten Anhängen |
TRAEFIK_NETWORK |
Vorhandenes Traefik-Netz, standardmäßig dokploy-network |
POSTGRES_USER und POSTGRES_DB sind standardmäßig taskmanager; bei Änderungen die DATABASE_URL entsprechend anpassen. Bei einem bereits initialisierten Daten-Volume ändern diese Variablen weder vorhandene Benutzer noch Passwörter. Keine PostgreSQL-Daten einer anderen Hauptversion direkt einhängen.
Die App hängt am privaten Compose-Netz und am Proxy-Netz. DB, Migrator und Worker hängen nur am Compose-Netz; kein Dienst veröffentlicht Host-Ports. In Dokploy unter Domains die gewünschte Domain dem Dienst app, Container-Port 3000, zuweisen und HTTPS mit Zertifikat aktivieren. Dokploy verwaltet dafür die Traefik-Router. Die Compose-Datei allein legt keinen Domain-Router an. Keine alten statischen /uploads-Freigaben übernehmen. TRUST_PROXY=false belassen, bis der Proxy eingehendes X-Real-IP nachweislich zuverlässig ersetzt.
Bestehende Daten übernehmen
Vor dem ersten vollständigen Deployment UPGRADE.md ausführen: Altanwendung stoppen, zusammengehöriges Datenbank-/Dateibackup erstellen, in separate Ziel-Volumes wiederherstellen und abnehmen. Die Compose-Datei kopiert keine Daten aus einer anderen Installation. Externe Volumes werden absichtlich nicht automatisch angelegt: ein falscher Name soll zum Fehler führen, statt unbemerkt eine leere Datenbank zu starten.
Nur für eine neue, separate Zielinstallation zwei noch nicht vorhandene Volume-Namen wählen, deren Nichtexistenz prüfen und sie dann mit docker volume create NAME anlegen. Namen in der Umgebung hinterlegen. Alte Volumes unangetastet lassen. Für die Befehle aus UPGRADE.md stets denselben Projektnamen und diese Compose-Datei verwenden. In Bash hilft folgende Funktion (auch für Restore und Abnahme):
dc() { docker compose --env-file .env.production -p taskmanager-next -f docker-compose.production.yml "$@"; }
dc config --quiet
docker login git.jfritzsche.de --username jf
dc pull
dc up -d --wait db
# Jetzt DB-Dump und Anhänge gemäß UPGRADE.md wiederherstellen.
# Dort "docker compose -p taskmanager-next" jeweils durch "dc" ersetzen.
In Dokploy stattdessen dessen tatsächlichen Projektnamen und dieselbe Umgebung verwenden; nicht parallel ein zweites CLI-Projekt auf denselben DB-Volumes starten. Bei privaten Images die Registry-Anmeldung auch für Dokploy hinterlegen. Zum Wiederherstellen der Dateien nutzt UPGRADE.md kurzzeitig UID 0; die regulären Anwendungsdienste laufen als UID 1001. Anhänge müssen dieser UID gehören. Eine gegebenenfalls erforderliche Prisma-Baseline nach UPGRADE.md prüfen, nicht automatisch setzen.
Nach Restore und Prüfung der Migrationshistorie:
dc run --rm migrate
# Nur bei Erfolg fortfahren; Bestandsmengen gemäß UPGRADE.md vergleichen.
dc up -d --wait app
# Login, Bestandsdaten und Downloads prüfen, noch im Wartungsmodus.
dc up -d --wait worker
dc ps -a
dc logs --tail=100 migrate app worker
Beim regulären vollständigen Compose-Start erzwingt die Abhängigkeitskette: gesunde DB → erfolgreiche Schema-, RBAC- und Datei-Migration → gesunde App → Worker. migrate-access.ts führt den RBAC-Seed aus; anschließend an die Datei-Migration läuft prisma/seed.ts (einschließlich idempotentem RBAC-Seed). Ist bereits ein Systemadministrator vorhanden, wird dessen Anlage übersprungen. Andernfalls sind BOOTSTRAP_EMAIL und BOOTSTRAP_PASSWORD erforderlich; ohne diese Werte bricht der Start ab. Bestehende Konten und Passwörter werden nicht überschrieben. Bei einem Upgrade ohne Administrator zuerst die wiederhergestellten Bestandsdaten prüfen, bevor ein neues Administratorkonto angelegt wird. Ein fehlgeschlagener Migrator blockiert den Start abhängiger Dienste, stoppt aber keine bereits laufende alte App: deshalb vor Updates immer App und Worker stoppen.
Weitere Updates
Zusammengehöriges Backup erstellen, Schreibzugriffe verhindern und dc stop app worker ausführen. Dann TASKMANAGER_VERSION auf die nächste geprüfte Version setzen, dc pull, dc run --rm migrate und erst nach erfolgreicher Migration dc up -d --wait app worker ausführen. Keine gleichzeitigen Deployments oder Migratoren. ARCHIVE_RETENTION_DAYS=0 verhindert automatische dauerhafte Archivbereinigung. Rollback und Backups stehen in UPGRADE.md und README.md.
Erstes Administratorkonto
Bei einer bestätigten Neuinstallation BOOTSTRAP_EMAIL und BOOTSTRAP_PASSWORD setzen (Passwort mindestens 12 Zeichen, maximal 72 UTF-8-Bytes). Diese Werte erhält in den Produktionsdateien ausschließlich der Migrator. Nach erfolgreichem Bootstrap aus der Umgebung entfernen und den beendeten Migrationscontainer entfernen, damit dessen alte Umgebung nicht gespeichert bleibt (dc rm -f migrate). Bei der ersten Anmeldung ist eine Passwortänderung erforderlich. Bei vorhandenen Administratoren können beide Werte leer bleiben. scripts/seed-demo.ts wird niemals beim Produktionsstart ausgeführt.