114 lines
5.2 KiB
Markdown
114 lines
5.2 KiB
Markdown
# 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.
|