fix(db): auto-create DB directory and improve open error messages
Open() now creates the parent directory of the database path itself, so e.g. DB_PATH=/data/app.db works on first start without a prior mkdir. Open, ping, and migration errors are wrapped with context and hints about writable directories and Docker bind-mount ownership (chown 1000:1000 or use a named volume). Also add a README troubleshooting section for the "database could not be opened" error.
This commit is contained in:
parent
d096295997
commit
bfae47f584
2 changed files with 24 additions and 3 deletions
|
|
@ -92,6 +92,14 @@ Hinter einem Reverse-Proxy / mit Domain zusätzlich setzen:
|
||||||
|
|
||||||
Wichtig: `JWT_SECRET` und `ENCRYPTION_KEY` dauerhaft setzen (Container-Neustarts sonst neue Secrets → Logins/Token ungültig), und die Google-Redirect-URI auf `{APP_URL}/api/calendars/google/callback` konfigurieren. Das SQLite-File liegt im Volume `/data`.
|
Wichtig: `JWT_SECRET` und `ENCRYPTION_KEY` dauerhaft setzen (Container-Neustarts sonst neue Secrets → Logins/Token ungültig), und die Google-Redirect-URI auf `{APP_URL}/api/calendars/google/callback` konfigurieren. Das SQLite-File liegt im Volume `/data`.
|
||||||
|
|
||||||
|
**Troubleshooting „Datenbank konnte nicht geöffnet werden“:** Der Server legt Verzeichnis und Datei selbst an, braucht dafür aber Schreibrechte. Der Container läuft als User 1000 (`app`). Bei einem **Bind-Mount** (`-v /pfad/auf/host:/data`) muss das Host-Verzeichnis diesem User gehören:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo chown -R 1000:1000 /pfad/auf/host
|
||||||
|
```
|
||||||
|
|
||||||
|
Docker erstellt nicht-existierende Bind-Mount-Pfade automatisch als root – deshalb entweder den Pfad vorher anlegen und `chown`en, oder den **Named Volume** nutzen (`-v wannpassts-data:/data` bzw. die docker-compose.yml), wo das automatisch passt.
|
||||||
|
|
||||||
### PWA-Hinweise
|
### PWA-Hinweise
|
||||||
|
|
||||||
- Der Service Worker wird nur im Production-Build registriert (`npm run build` + Auslieferung über `STATIC_DIR`), nicht im Vite-Dev-Modus.
|
- Der Service Worker wird nur im Production-Build registriert (`npm run build` + Auslieferung über `STATIC_DIR`), nicht im Vite-Dev-Modus.
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,9 @@ package db
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
_ "modernc.org/sqlite"
|
_ "modernc.org/sqlite"
|
||||||
|
|
@ -63,18 +66,28 @@ type Booking struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Open(path string) (*DB, error) {
|
func Open(path string) (*DB, error) {
|
||||||
|
// Übergeordnetes Verzeichnis selbst anlegen, damit z. B. DB_PATH=/data/app.db
|
||||||
|
// beim ersten Start funktioniert, ohne dass jemand vorab mkdir ausführt.
|
||||||
|
if dir := filepath.Dir(path); dir != "" && dir != "." {
|
||||||
|
if err := os.MkdirAll(dir, 0o755); err != nil {
|
||||||
|
return nil, fmt.Errorf("Datenbank-Verzeichnis %s konnte nicht angelegt werden (Berechtigungen prüfen): %w", dir, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
d, err := sql.Open("sqlite", "file:"+path+"?_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)&_pragma=foreign_keys(1)")
|
d, err := sql.Open("sqlite", "file:"+path+"?_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)&_pragma=foreign_keys(1)")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("Datenbank %s konnte nicht geöffnet werden: %w", path, err)
|
||||||
}
|
}
|
||||||
// SQLite verträgt parallele Writer nicht gut – ein Writer reicht hier.
|
// SQLite verträgt parallele Writer nicht gut – ein Writer reicht hier.
|
||||||
d.SetMaxOpenConns(1)
|
d.SetMaxOpenConns(1)
|
||||||
if err := d.Ping(); err != nil {
|
if err := d.Ping(); err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf(
|
||||||
|
"Datenbank %s konnte nicht geöffnet oder angelegt werden: %w – "+
|
||||||
|
"ist das Verzeichnis beschreibbar? (Docker: Bind-Mounts müssen dem Container-User gehören, z. B. `sudo chown -R 1000:1000 <host-pfad>`; bei Named Volumes passiert das automatisch)",
|
||||||
|
path, err)
|
||||||
}
|
}
|
||||||
dbase := &DB{d}
|
dbase := &DB{d}
|
||||||
if err := dbase.migrate(); err != nil {
|
if err := dbase.migrate(); err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("Datenbank-Schema konnte nicht initialisiert werden: %w", err)
|
||||||
}
|
}
|
||||||
return dbase, nil
|
return dbase, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue