Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Datenbanken 14.08.2026 · 10 min Lesezeit

Directus mit Docker installieren: Jede SQL-Datenbank sofort als REST- und GraphQL-API bereitstellen

Directus legt sich nicht-destruktiv über jede SQL-Datenbank und generiert automatisch REST- und GraphQL-API – ohne Schema-Migration. Diese Anleitung zeigt, wie du Directus v12 mit Docker Compose, PostgreSQL und Redis in unter 20 Minuten produktionsreif aufsetzt.

Directus mit Docker installieren: SQL-Datenbank als REST- und GraphQL-API bereitstellen mit Datenmodell, Benutzerverwaltung, Berechtigungen, Docker Container und Server-Infrastruktur. KI-generiert

Wer eine bestehende PostgreSQL-, MySQL- oder MariaDB-Datenbank hat und daraus schnell eine REST- oder GraphQL-API machen möchte, ohne das Schema anzufassen, für den ist Directus die überzeugendste Lösung am Markt. Das Open-Source-Projekt (36.000+ GitHub-Stars, v12.0.1, Stand Juni 2026) legt sich als nicht-destruktive Schicht über jede unterstützte SQL-Datenbank, erkennt alle bestehenden Tabellen automatisch als „Collections" und generiert sofort eine vollständige OpenAPI-3.0-konforme REST-API sowie eine GraphQL-API – ohne eine einzige Codezeile selbst zu schreiben. Dazu kommt eine moderne Admin-UI (Vue.js), über die auch nicht-technische Kolleginnen und Kollegen Inhalte pflegen, Zugriffsrechte vergeben und einfache Automatisierungen (Flows) erstellen können. Diese Anleitung richtet sich an KMU-Admins, Entwickler und ambitionierte Selfhoster, die Directus plattformneutral per Docker Compose auf einem Linux-Server, einer VM oder einem NAS mit Docker-Unterstützung betreiben wollen.

Voraussetzungen

  1. Docker Engine v24+ und Docker Compose Plugin v2.20+ auf dem Host installiert – falls nicht, hilft die Grundlagenanleitung Docker und Docker Compose auf Linux installieren.
  2. Linux-Host, VM oder NAS mit Docker-Unterstützung (Ubuntu, Debian, Synology mit Container Manager, Hetzner-VPS o. ä.); das Image unterstützt linux/amd64 und linux/arm64 nativ.
  3. Mindestens 1 GB RAM (empfohlen: 2 GB+) für Directus + PostgreSQL + Redis zusammen.
  4. Persistenter Speicher für Datenbank-Volume und Datei-Uploads.
  5. openssl verfügbar, um einen kryptografisch sicheren SECRET-Wert zu erzeugen.
  6. Optional: Reverse Proxy (Caddy, Traefik, nginx) für TLS/HTTPS in Produktion – siehe Caddy als Reverse Proxy mit automatischem HTTPS.

Eckdaten auf einen Blick

ParameterWert
Docker-Imagedirectus/directus:12.0.1
Image-Größeca. 227 MB
Architekturenlinux/amd64, linux/arm64
Standard-Port8055 (HTTP, intern fest)
Datenbank-Imagepostgis/postgis:16-3.4
Cache-Imageredis:7-alpine
LizenzMSCL 1.0 – kostenlos bis 5 Mio. USD / 50 MA
Admin-UIhttp://localhost:8055
Volume (Host → Container)ZweckPflicht?
./uploads → /directus/uploadsHochgeladene Dateien und AssetsJa
./extensions → /directus/extensionsEigene Hooks, Endpoints, InterfacesOptional
./data/database → /var/lib/postgresql/dataPostgreSQL-DatenbankdateienJa

Schritt 1: Projektordner anlegen

Lege einen dedizierten Ordner für das Directus-Projekt an. Alle Compose-Dateien, die .env und die persistenten Daten landen hier.

mkdir -p /opt/directus
cd /opt/directus
mkdir -p data/database uploads extensions

Die drei Unterordner sorgen dafür, dass Docker sie beim ersten Start nicht als root anlegt und dann Berechtigungsprobleme entstehen.

Verifizieren: ls -la /opt/directus zeigt die Ordner data/, uploads/ und extensions/. Alle drei Verzeichnisse vorhanden, Eigentümer ist der aktuelle Nutzer.

Schritt 2: .env-Datei mit sicheren Geheimnissen anlegen

Directus bezieht seine gesamte Konfiguration aus Umgebungsvariablen. Die kritischste Variable ist SECRET – sie signiert alle JWT-Tokens und Sessions. Ein unsicherer Wert hier bedeutet vollständige Kompromittierung der Instanz.

Erzeuge zunächst drei sichere Zufallswerte:

# SECRET (mindestens 32 Zeichen, kryptografisch sicher)
openssl rand -base64 32

# DB_PASSWORD
openssl rand -base64 24

# ADMIN_PASSWORD (merken oder in Passwortmanager speichern)
openssl rand -base64 16

Lege dann die .env-Datei an und trag die erzeugten Werte ein:

# /opt/directus/.env
# --- Datenbank ---
DB_USER=directus
DB_PASSWORD=HIER_SICHERES_PASSWORT_EINTRAGEN
DB_DATABASE=directus

# --- Directus Core ---
SECRET=HIER_32_ZEICHEN_ZUFALLSSTRING_EINTRAGEN

# --- Erster Admin-Account (nur beim allerersten Start ausgewertet) ---
ADMIN_EMAIL=admin@example.com
ADMIN_PASSWORD=HIER_SICHERES_ADMIN_PASSWORT

# --- Öffentliche URL (für E-Mails, Datei-URLs, OAuth) ---
PUBLIC_URL=http://localhost:8055

Schränke die Dateiberechtigungen sofort ein, damit andere Nutzer auf dem System die Passwörter nicht lesen können:

chmod 600 /opt/directus/.env

Wichtiger Hinweis zur Lizenz: Directus steht unter der Monospace Sustainable Core License (MSCL) 1.0. Die kostenlose Nutzung ist auf Organisationen mit unter 5 Mio. USD Jahresumsatz und unter 50 Mitarbeitern beschränkt. Größere Organisationen benötigen eine kommerzielle Lizenz.

Verifizieren: cat /opt/directus/.env zeigt alle Variablen mit ausgefüllten Werten, kein Platzhalter mehr. ls -la /opt/directus/.env zeigt Berechtigungen -rw-------.

Schritt 3: compose.yaml erstellen

Die folgende compose.yaml startet drei Services: PostgreSQL mit PostGIS-Erweiterung (empfohlen für Geospatial-Support, läuft identisch für Standard-Use-Cases), Redis als Cache und Directus selbst. Entscheidend sind die healthcheck-Definitionen und die depends_on-Bedingungen – ohne sie würde Directus starten, bevor die Datenbank bereit ist, und mit einem ECONNREFUSED-Fehler abstürzen.

# /opt/directus/compose.yaml
services:

  database:
    image: postgis/postgis:16-3.4
    container_name: directus_db
    restart: unless-stopped
    volumes:
      - ./data/database:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: ${DB_USER:-directus}
      POSTGRES_PASSWORD: ${DB_PASSWORD:?DB_PASSWORD ist erforderlich}
      POSTGRES_DB: ${DB_DATABASE:-directus}
    healthcheck:
      test: ["CMD", "pg_isready", "--host=localhost", "--username=${DB_USER:-directus}"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

  cache:
    image: redis:7-alpine
    container_name: directus_cache
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "redis-cli ping | grep -q PONG"]
      interval: 10s
      timeout: 5s
      retries: 5

  directus:
    image: directus/directus:12.0.1
    container_name: directus_app
    restart: unless-stopped
    ports:
      - "8055:8055"
    volumes:
      - ./uploads:/directus/uploads
      - ./extensions:/directus/extensions
    depends_on:
      database:
        condition: service_healthy
      cache:
        condition: service_healthy
    environment:
      SECRET: ${SECRET:?SECRET ist erforderlich}
      DB_CLIENT: "pg"
      DB_HOST: "database"
      DB_PORT: "5432"
      DB_DATABASE: ${DB_DATABASE:-directus}
      DB_USER: ${DB_USER:-directus}
      DB_PASSWORD: ${DB_PASSWORD:?DB_PASSWORD ist erforderlich}
      ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@example.com}
      ADMIN_PASSWORD: ${ADMIN_PASSWORD:?ADMIN_PASSWORD ist erforderlich}
      PUBLIC_URL: ${PUBLIC_URL:-http://localhost:8055}
      CACHE_ENABLED: "true"
      CACHE_STORE: "redis"
      REDIS: "redis://cache:6379"

Zwei Designentscheidungen sind hier bewusst getroffen: Die Syntax ${VARIABLE:?Fehlermeldung} für alle Pflichtfelder lässt Docker Compose sofort mit einer verständlichen Fehlermeldung abbrechen, wenn die .env unvollständig ist. Redis ist bereits integriert, da er für Produktionsinstanzen mit mehreren gleichzeitigen Nutzern dringend empfohlen wird und kaum Ressourcen kostet.

Verifizieren: docker compose config im Projektordner löst alle Variablen auf und zeigt die fertige Konfiguration ohne Fehler. Jede nicht gesetzte Pflicht-Variable erzeugt eine unmittelbare Fehlermeldung.

Schritt 4: Stack starten und Erst-Initialisierung abwarten

Starte alle drei Container im Hintergrund:

cd /opt/directus
docker compose up -d

Beim allerersten Start legt Directus automatisch alle eigenen Systemtabellen (Präfix directus_) in der Datenbank an und richtet den Admin-Account ein. Dieser Vorgang dauert typischerweise 30–60 Sekunden. Beobachte den Fortschritt mit:

docker compose logs -f directus

Warte, bis du eine Zeile siehst, die in etwa lautet:

Server started at http://0.0.0.0:8055

Prüfe anschließend den Status aller Container:

docker compose ps

Erwartete Ausgabe (alle drei Container im Status Up (healthy)):

NAME              IMAGE                        STATUS
directus_app      directus/directus:12.0.1     Up (healthy)
directus_cache    redis:7-alpine               Up (healthy)
directus_db       postgis/postgis:16-3.4       Up (healthy)

Verifizieren: Führe einen HTTP-Check auf den Health-Endpunkt durch. Für Docker-Healthchecks immer /server/ping statt /server/health verwenden, da Letzterer CPU-intensiv alle Abhängigkeiten prüft:

curl -s http://localhost:8055/server/ping

Erwartete Antwort: pong

Schritt 5: Admin-UI öffnen und erste Schritte

Öffne im Browser http://localhost:8055 (bzw. die IP-Adresse deines Servers). Melde dich mit der ADMIN_EMAIL und dem ADMIN_PASSWORD aus der .env-Datei an.

Nach dem Login siehst du das Directus-Dashboard. Unter Settings → Data Model erscheinen alle Tabellen deiner Datenbank automatisch als Collections – du hast sie nicht angelegt, Directus hat sie beim Start erkannt. Unter Settings → API Documentation findest du die automatisch generierte OpenAPI-Spezifikation.

Wenn du Directus mit einer bestehenden Datenbank verbinden willst (Legacy-Modernisierung), ändere in der .env die Verbindungsparameter (DB_HOST, DB_PORT, DB_DATABASE, DB_USER, DB_PASSWORD) auf deinen bestehenden Datenbankserver und setze DB_CLIENT entsprechend: mysql für MySQL/MariaDB, mssql für SQL Server, sqlite3 für SQLite. Directus fügt lediglich seine eigenen directus_*-Tabellen hinzu – keine bestehende Tabelle oder Datenzeile wird verändert.

Verifizieren: Öffne im Browser http://localhost:8055 – die Directus-Anmeldeseite erscheint. Nach dem Login ist das Dashboard sichtbar. Teste die REST-API direkt per curl:

curl -s http://localhost:8055/server/info | head -c 200

Erwartete Antwort: JSON-Objekt mit Directus-Versionsinformationen und HTTP-Statuscode 200.

Schritt 6: REST-API und GraphQL ausprobieren

Directus generiert für jede Collection automatisch REST-Endpunkte nach dem Muster /items/<collection-name>. Für die GraphQL-API steht /graphql bereit. Hole zunächst ein temporäres Token für den Admin-Account:

curl -s -X POST http://localhost:8055/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@example.com","password":"DEIN_ADMIN_PASSWORT"}' \
  | python3 -m json.tool

Die Antwort enthält ein access_token. Damit kannst du beliebige Collections abfragen:

curl -s http://localhost:8055/items/DEINE_TABELLE \
  -H "Authorization: Bearer DEIN_ACCESS_TOKEN" \
  | python3 -m json.tool

Die OpenAPI-Dokumentation ist interaktiv unter http://localhost:8055/server/specs/oas abrufbar und lässt sich direkt in Swagger UI, Postman oder Insomnia importieren.

Verifizieren: Das Login-Kommando liefert ein JSON-Objekt mit "access_token"-Feld, HTTP-Statuscode 200. Der Collections-Aufruf liefert ein JSON-Array mit den Tabellenzeilen oder eine leere Liste {"data":[]} bei leerer Tabelle.

Schritt 7: Reverse Proxy und HTTPS einrichten (Produktion)

Directus lauscht intern immer auf Port 8055; TLS wird über einen vorgelagerten Reverse Proxy terminiert. Für automatisches HTTPS empfiehlt sich Caddy als Reverse Proxy oder Traefik als Docker-Reverse-Proxy. Passe nach dem HTTPS-Setup die PUBLIC_URL in der .env-Datei an:

PUBLIC_URL=https://directus.example.com

Starte den Stack danach neu, damit Directus die neue URL für Datei-Links, E-Mails und OAuth-Callbacks verwendet:

docker compose up -d

Verifizieren: curl -I https://directus.example.com/server/ping gibt HTTP/2 200 zurück. In der Admin-UI unter Settings → Project steht die korrekte öffentliche URL.

Schritt 8: Updates und Backups

Directus führt Datenbankmigrationen beim Start automatisch durch. Das Update-Verfahren ist daher einfach – Image-Tag in der compose.yaml anpassen, dann:

cd /opt/directus
docker compose pull
docker compose up -d
docker compose logs -f directus

Vor jedem Update immer zuerst ein Datenbank-Backup erstellen:

docker exec directus_db pg_dump -U directus directus > backup_$(date +%Y%m%d).sql

Wie du PostgreSQL-Backups automatisierst und per rclone in die Cloud spiegelst, erklärt MySQL & PostgreSQL Backup automatisieren mit cron. Grundlagen zu Docker-Volumes findest du unter Docker-Netzwerke und Volumes richtig nutzen.

Verifizieren: docker compose ps zeigt alle Container mit dem neuen Image-Tag im Status Up (healthy). curl -s http://localhost:8055/server/info gibt die neue Versionsnummer zurück.

Troubleshooting / Typische Fehler

  1. „SECRET is required" beim Start: Die SECRET-Variable fehlt in der .env oder ist leer. Lösung: openssl rand -base64 32 ausführen und den Wert eintragen.
  2. „ECONNREFUSED" oder Datenbankverbindung schlägt fehl: Directus startet, bevor PostgreSQL bereit ist. Lösung: healthcheck am database-Service und depends_on mit condition: service_healthy wie in der obigen compose.yaml sicherstellen.
  3. Admin-Login nach erstem Start schlägt fehl: ADMIN_EMAIL/ADMIN_PASSWORD werden nur beim allerersten Datenbanksetup ausgewertet. Danach nur noch via Directus-UI änderbar – „Passwort vergessen" auf der Login-Seite nutzen.
  4. Uploads nach Container-Neustart weg: Das Volume ./uploads:/directus/uploads fehlt oder ist nicht korrekt gemountet. Volume-Eintrag prüfen und Container neu starten.
  5. „Public URL mismatch" bei Datei-URLs oder OAuth: PUBLIC_URL stimmt nicht mit der tatsächlichen externen URL überein (z. B. http statt https, fehlender Port). PUBLIC_URL exakt auf die extern erreichbare URL setzen und Container neu starten.
  6. Hohe CPU-Last durch Docker-Healthcheck: /server/health als Healthcheck-Endpunkt prüft alle Abhängigkeiten aufwändig. Lösung: Immer /server/ping für Healthchecks verwenden – das ist ein reiner HTTP-Check ohne Diagnose-Overhead.
  7. Extension lädt nicht / „Cannot find module": Das Volume ./extensions:/directus/extensions ist nicht gemountet oder die Extension liegt nicht im richtigen Unterverzeichnis (z. B. extensions/hooks/). Volume-Mount prüfen, Verzeichnisstruktur beachten.
  8. Lizenzverstoß: Directus in einer Organisation mit über 5 Mio. USD Umsatz oder über 50 Mitarbeitern ohne kommerzielle Lizenz einsetzen. Lösung: Kommerzielle Lizenz erwerben oder Open Innovation Grant beantragen.

Häufige Fragen

Kann ich Directus mit einer bestehenden Datenbank verbinden, ohne Daten zu verändern?

Ja, das ist der Kern-Use-Case von Directus. Das System liest das Schema der bestehenden Datenbank aus und generiert automatisch API-Endpunkte für alle vorhandenen Tabellen. Es verändert keine bestehenden Tabellen oder Datenzeilen. Directus fügt lediglich eigene Systemtabellen mit dem Präfix directus_ hinzu. Dieses nicht-destruktive Prinzip macht Directus zur idealen Lösung für die Modernisierung von Legacy-Datenbanken ohne Risiko.

Welche Datenbanken werden unterstützt?

PostgreSQL (empfohlen, am besten getestet), MySQL 5.7+/8, MariaDB 10.3+, SQLite 3 (gut für lokale Tests ohne separaten Container: DB_CLIENT=sqlite3, DB_FILENAME=/directus/database.db), MS SQL Server 2019+, OracleDB 18+ und CockroachDB 24+. Der Datenbanktyp wird über DB_CLIENT gesteuert: pg, mysql, mysql2, sqlite3, mssql, oracledb oder cockroachdb.

Ist Redis Pflicht?

Nein, Redis ist optional. Für lokale Entwicklung oder kleine Instanzen mit wenigen Nutzern läuft Directus auch ohne Cache. Für Produktionsinstanzen mit mehreren gleichzeitigen Nutzern ist Redis-Caching jedoch dringend empfohlen, da es die Antwortzeiten deutlich verbessert. Da redis:7-alpine nur wenige MB Speicher benötigt, lohnt es sich, ihn von Anfang an einzubinden.

Funktioniert Directus auf ARM64 (Raspberry Pi, Apple Silicon, Hetzner ARM)?

Ja, das offizielle Docker-Image directus/directus unterstützt linux/arm64 nativ. Es ist kein Emulations-Overhead und keine Anpassung an der Compose-Datei nötig – Docker wählt automatisch das passende Image für die Host-Architektur.

Wie aktualisiere ich Directus auf eine neue Version?

Den Image-Tag in der compose.yaml anpassen, dann docker compose pull && docker compose up -d ausführen. Directus führt alle notwendigen Datenbankmigrationen beim Start automatisch durch. Vor dem Update immer ein Datenbank-Backup erstellen – ein pg_dump im Container genügt.

Was ist der Unterschied zwischen dem GitHub-Compose und der Produktions-Vorlage?

Das docker-compose.yml im Directus-GitHub-Repository startet 14 Services mit allen unterstützten Datenbanken gleichzeitig und ist ausdrücklich nur für das Debugging des Directus-Kernteams gedacht. Für den eigenen Betrieb immer die offizielle Dokumentation unter directus.com/docs/self-hosted/docker-guide.html als Referenz nutzen.

Fazit

Directus ist eine der wenigen Open-Source-Lösungen, die wirklich halten, was sie versprechen: Eine bestehende SQL-Datenbank wird ohne Schema-Änderungen, ohne Codeaufwand und in unter 20 Minuten zu einer vollständigen REST- und GraphQL-API mit Admin-UI. Der Docker-Stack aus drei Containern (Directus, PostgreSQL, Redis) ist überschaubar, gut zu warten und läuft auf jedem System mit Docker-Unterstützung. Für KMU, die Altdaten modernisieren oder ein flexibles Backend-as-a-Service benötigen, ist Directus ein ernstzunehmender Kandidat. Lizenz (MSCL 1.0) und die kryptografisch sichere SECRET-Variable nicht vernachlässigen – beides hat in der Praxis reale Konsequenzen.

Weiterführende Anleitungen und Quellen

  1. Docker und Docker Compose auf Linux installieren – die Self-Hosting-Grundlage
  2. MySQL & PostgreSQL Backup automatisieren mit cron, pg_dump und rclone
  3. Caddy als Reverse Proxy mit automatischem HTTPS einrichten
  4. PostgreSQL pg_dump und pg_restore: Backup und Migration per Kommandozeile
  5. Docker-Netzwerke und Volumes richtig nutzen
  6. Hasura mit Docker: sofortige GraphQL-API über bestehende Datenbanken

Offizielle Quellen: Directus Docker Guide | Directus auf GitHub | Directus auf Docker Hub | Directus Konfigurationsoptionen