# 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. ```sh 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 ```sh 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: ```sh 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 ```sh 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 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: ```sh 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.