Files
Inventory/docs/postgresql-migration.md
2026-09-29 08:43:05 +02:00

5.2 KiB

SQLite → PostgreSQL mit Docker

Die Anwendung verwendet standardmäßig PostgreSQL. Es gibt keinen automatischen Rückfall auf SQLite. Die folgenden Befehle sind vorbereitet; sie wurden auf dem aktuellen Windows-Rechner ohne Docker nicht ausgeführt.

Vorbereiten

Docker mit Compose muss verfügbar sein. Die Befehle im Projektverzeichnis ausführen. Die bisherige Anwendung während Export, Import und Prüfung stoppen, damit keine Änderungen nach dem Export verloren gehen. db.sqlite3 und das Verzeichnis media behalten und zusätzlich extern sichern. Niemals docker compose down -v ausführen, wenn Volumes noch benötigte Daten enthalten.

.env.example nach .env kopieren und mindestens SECRET_KEY, POSTGRES_PASSWORD, Domain, erlaubte Hosts und CSRF-Origin ersetzen. POSTGRES_HOST=db beibehalten. Keine Zugangsdaten in Git ablegen.

docker compose config --quiet
docker compose --profile tools build web migration
docker compose stop web traefik
docker compose up -d --wait db

Die Zieldatenbank muss leer sein. Vor dem Import den Webdienst noch nicht starten: Sein Startskript legt sonst bereits Seed-Daten an. Das Importkommando verweigert einen Import, sobald Benutzer, Gruppen oder Inventardaten vorhanden sind. Die zwei von Migration 0003 angelegten Standard-Gerätetypen werden als leere Ausgangsbasis erkannt und innerhalb der Importtransaktion durch die Exportdaten ersetzt. Ein vorhandenes PostgreSQL-System niemals zum Zweck des Imports leeren; stattdessen eine neue Datenbank bzw. ein separates Compose-Projekt verwenden.

Exportieren, Schema anlegen, importieren

docker compose run --rm migration scripts/export_sqlite.py /legacy/db.sqlite3 /transfer/sqlite-export.json
docker compose run --rm migration manage.py migrate --noinput
docker compose run --rm migration manage.py import_sqlite_export /transfer/sqlite-export.json

Der Export liest SQLite über eine schreibgeschützte Verbindung, erstellt einen konsistenten temporären Snapshot und aktualisiert nur dessen Schema. Die originale SQLite-Datei bleibt unverändert. Existiert die Exportdatei bereits, wird sie nicht überschrieben; für einen weiteren Export einen neuen Dateinamen verwenden.

Der Export enthält Benutzer und Passwort-Hashes, Rollen, API-Schlüssel-Hashes, Geräte, Archivstatus, Zusatzfelder, Einstellungen, Nummernfolge und Historie. Content Types und Standardberechtigungen werden durch Migrationen angelegt und über natürliche Schlüssel zugeordnet. Sitzungen werden nicht übernommen; Benutzer müssen sich erneut anmelden. Der Import läuft transaktional und setzt die PostgreSQL-ID-Sequenzen durch Djangos loaddata zurück. Die Gerätenummernfolge wird mindestens auf die höchste vorhandene Gerätenummer gesetzt.

backups/sqlite-export.json enthält vertrauliche Daten und ist kein öffentliches Download-Artefakt. Der Export setzt auf Linux Dateirechte 0600. Der offline gestartete Migrationscontainer läuft für den Zugriff auf das Backup-Verzeichnis als root; der Webcontainer läuft weiterhin als unprivilegierter app-Benutzer.

Uploads übernehmen

Der Datenbankexport enthält Dateiverweise, nicht die Dateien selbst. Bei einem neuen, leeren media_data-Volume die bisherigen Uploads kopieren:

docker compose run --rm --entrypoint sh migration -c 'cp -a /legacy/media/. /app/media/ && chown -R app:app /app/media'

Ein bereits verwendetes Medienvolume zuerst sichern und seine Inhalte separat abgleichen; der Kopierbefehl darf nicht ungeprüft über vorhandene Dateien laufen.

Prüfen und starten

docker compose run --rm migration manage.py check
docker compose run --rm migration manage.py makemigrations --check --dry-run
docker compose run --rm -e DEBUG=true -e SECURE_SSL_REDIRECT=false migration manage.py test --noinput
docker compose up -d --build web traefik
docker compose ps

Die Tests verwenden eine separate PostgreSQL-Testdatenbank. Danach Anmeldung, Geräteanzahl einschließlich Archiv, höchste Gerätenummer, Rollen, Historie und Upload-Verweise mit dem bisherigen System vergleichen. Ein PostgreSQL-Backup anlegen und testweise in eine separate leere Datenbank wiederherstellen:

sh scripts/backup.sh

Erst nach erfolgreicher Prüfung das alte System endgültig stilllegen. Für einen Rückwechsel den neuen Webdienst stoppen und die alte Anwendung mit ihrer unveränderten SQLite-Datei starten. Neue PostgreSQL-Änderungen werden nicht automatisch zurück nach SQLite übertragen.

Lokaler Docker-Betrieb ohne HTTPS-Domain

Nach dem Import alternativ nur Datenbank und Webdienst starten:

docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build db web

Die Anwendung ist dann unter http://localhost:8000 erreichbar. Der Port ist nur an localhost gebunden. Diese Entwicklungsüberschreibung nicht auf dem VPS nutzen.

Bearbeitungsversionen

Geräte besitzen nun eine ganzzahlige revision. Browser-Formulare senden expected_revision; API-PATCH-Anfragen können ebenfalls dieses Feld verwenden. Bestehende API-Clients mit expected_updated_at bleiben kompatibel. Veraltete Versionen werden abgewiesen. Zeitstempel steigen auch bei geringer Auflösung der Systemuhr strikt an. Migration 0006 setzt bestehende Geräte auf Revision 1.