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

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

Directus legt sich nicht-destruktiv über eine bestehende SQL-Datenbank und stellt sie als REST- und GraphQL-API bereit. Die Anleitung richtet Directus 12.5 mit Docker Compose, PostgreSQL und Redis ein und erklärt Update, Backup und Lizenzgrenzen.

Werbung Mit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen. Mehr dazu

Titelbild: Directus mit Docker installieren, SQL, REST, GraphQL

Directus legt sich als nicht-destruktive Schicht über eine bestehende PostgreSQL-, MySQL- oder MariaDB-Datenbank: Es erkennt vorhandene Tabellen als „Collections“ und stellt sie ohne eigenen Code als REST- und GraphQL-API bereit, inklusive OpenAPI-Spezifikation. Über die Admin-Oberfläche pflegen auch Fachabteilungen Inhalte, vergeben Rechte und bauen einfache Automatisierungen (Flows). Diese Anleitung richtet Directus 12.5.0 mit Docker Compose, PostgreSQL und Redis auf einem Linux-Server, einer VM oder einem NAS mit Docker ein.

Voraussetzungen

Eckdaten auf einen Blick

ParameterWert
Docker-Imagedirectus/directus:12.5.0
Image-Größeca. 240 MB (komprimiert)
Architekturenlinux/amd64, linux/arm64
Standard-Port8055 (HTTP, intern fest)
Datenbank-Imagepostgis/postgis:16-3.4
Cache-Imageredis:7-alpine
LizenzMSCL 1.0, kostenlose Core-Stufe mit Grenzen, darüber Lizenzschlüssel
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

Legen Sie 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

Vorab angelegt, erzeugt Docker die Ordner nicht als root; das vermeidet Berechtigungsprobleme.

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 liest seine Konfiguration aus Umgebungsvariablen. SECRET signiert alle Tokens (JWT) und Sitzungen; wer ihn kennt, kann sich beliebige Zugänge ausstellen. Erzeugen Sie drei 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

Legen Sie dann die .env-Datei an und tragen Sie 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

Beschränken Sie die Rechte, damit andere Nutzer die Passwörter nicht lesen:

$ chmod 600 /opt/directus/.env

Hinweis zur Lizenz: Directus steht unter der Monospace Sustainable Core License (MSCL) 1.0. Ohne Lizenzschlüssel läuft die kostenlose Core-Stufe; sie ist laut Hersteller auf 3 Nutzerplätze, 25 Collections und 5 Flows begrenzt. Höhere Grenzen erfordern eine kostenpflichtige Lizenz. Organisationen mit unter 5 Mio. USD Jahresumsatz und weniger als 50 Mitarbeitenden können das Open Innovation Grant beantragen und Directus selbst gehostet ohne diese Grenzen kostenlos nutzen. Bei bestehenden Datenbanken vorab prüfen, ob die Zahl der Tabellen passt.

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.5.0
    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"

Die Syntax ${VARIABLE:?Fehlermeldung} lässt Docker Compose sofort mit einer verständlichen Meldung abbrechen, wenn ein Pflichtwert in der .env fehlt. Redis dient als Cache und entlastet die Datenbank bei mehreren gleichzeitigen Nutzern.

docker compose config im Projektordner zeigt die aufgelöste Konfiguration ohne Fehler; fehlt eine Pflichtvariable, bricht es mit deren Meldung ab.

Schritt 4: Stack starten und Erst-Initialisierung abwarten

Starten Sie den Stack:

$ cd /opt/directus
$ docker compose up -d

Beim ersten Start legt Directus seine Systemtabellen (Präfix directus_) und den Admin-Account an; das dauert 30 bis 60 Sekunden. Fortschritt:

$ docker compose logs -f directus

Warten Sie auf eine Zeile wie:

Server started at http://0.0.0.0:8055

Dann den Status prüfen:

$ docker compose ps

Erwartet: alle drei Container laufen, Datenbank und Cache mit (healthy) (Directus hat hier keinen eigenen Healthcheck):

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

Prüfen Sie den Ping-Endpunkt. /server/ping ist laut Dokumentation der Endpunkt für Container-Healthchecks; /server/health prüft aufwendig alle Abhängigkeiten und antwortet ohne Token mit 403:

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

Erwartete Antwort: pong

Schritt 5: Admin-UI öffnen und erste Schritte

Öffnen Sie http://localhost:8055 (bzw. die IP-Adresse Ihres Servers) und melden Sie sich mit ADMIN_EMAIL und ADMIN_PASSWORD aus der .env an. Unter Settings → Data Model erscheinen die Tabellen Ihrer Datenbank als Collections. Unter Settings → API Documentation finden Sie die automatisch generierte OpenAPI-Spezifikation.

Für eine bestehende Datenbank tragen Sie deren DB_HOST, DB_PORT, DB_DATABASE, DB_USER und DB_PASSWORD ein und setzen DB_CLIENT passend (mysql für MySQL/MariaDB, mssql für SQL Server). Directus ergänzt nur seine directus_*-Tabellen, bestehende Tabellen und Daten bleiben unverändert.

Nach dem Login ist das Dashboard sichtbar. Testen Sie die API 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

Jede Collection erhält REST-Endpunkte nach dem Muster /items/<collection-name>, GraphQL liegt unter /graphql. Holen Sie ein temporäres Token für den Admin:

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

Mit dem access_token aus der Antwort fragen Sie Collections ab:

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

Die OpenAPI-Spezifikation liefert http://localhost:8055/server/specs/oas; sie lässt sich in Swagger UI, Postman oder Insomnia importieren.

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 auf Port 8055; TLS übernimmt ein vorgelagerter Reverse Proxy, etwa Caddy als Reverse Proxy oder Traefik als Docker-Reverse-Proxy. Passen Sie nach dem HTTPS-Setup die PUBLIC_URL in der .env-Datei an:

PUBLIC_URL=https://directus.example.com

Danach neu starten, damit Datei-Links, E-Mails und OAuth die neue URL nutzen:

$ docker compose up -d

curl -I https://directus.example.com/server/ping gibt HTTP/2 200 zurück, und die Anmeldeseite lädt über HTTPS ohne Zertifikatswarnung.

Schritt 8: Updates und Backups

Directus führt Datenbankmigrationen beim Start automatisch aus. Passen Sie den Image-Tag in der compose.yaml an und starten Sie neu:

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

Hinweise für das Update von 12.0 auf 12.5: Kein manueller Migrationsschritt nötig, aber laut Release Notes ändern sich Verhaltensweisen. Ab 12.1 entfallen /utils/hash/generate und /utils/hash/verify, WebSockets werden gegen CORS_ORIGIN geprüft, npm/npx fehlen im Image. Ab 12.2 ersetzt Tiptap den TinyMCE-Editor (Felder mit nicht übertragbarem Markup bleiben bis zur Bestätigung schreibgeschützt), Importe sind per IMPORT_MAX_FILE_SIZE auf 50 MB begrenzt. Ab 12.3 begrenzt ASSETS_TRANSFORM_IMAGE_MAX_OUTPUT_DIMENSION Bildtransformationen auf 6000 Pixel, die Flow-Operationen „Update Items“ und „Delete Items“ wirken ohne Schlüssel und Abfrage nicht mehr auf alle Einträge, und eigene Images müssen statt pm2-runtime docker-entrypoint.cjs aufrufen. Ab 12.4 brauchen Karten-Layout und Geometrie-Interface WebGL2, Update/Delete per Abfrage verlangt Leserechte auf den Primärschlüssel. Ab 12.5 lehnt Directus fehlerhafte Subnetze wie 10.0.0.0/ 24 in ip_access oder IMPORT_IP_DENY_LIST ab; betroffene Nutzer scheitern dann mit jeder Anfrage, korrigieren Sie solche Einträge vorher. CACHE_SCHEMA_MAX_ITERATIONS entfällt, CACHE_SCHEMA_SYNC_TIMEOUT (Standard 60000 ms) begrenzt jetzt auch den Schemaaufbau. Die Zwei-Faktor-Pflicht berücksichtigt die effektiven Berechtigungen einschließlich IP-Freigaben. Beim Update von 12.0.1 auf 12.4.1 und weiter auf 12.5.0 spielt Directus die Migrationen ein (Running migrations...), eine zuvor angelegte Collection mit Testdatensatz bleibt erhalten, /server/info meldet 12.5.0, und der Admin-Login funktioniert unverändert.

Vor jedem Update immer zuerst ein Datenbank-Backup erstellen:

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

Automatisierte Backups beschreibt MySQL & PostgreSQL Backup automatisieren mit cron, Volumes erklärt Docker-Netzwerke und Volumes richtig nutzen.

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

Troubleshooting / Typische Fehler

„SECRET is required“ beim Start

SECRET fehlt oder ist leer. Wert mit openssl rand -base64 32 erzeugen und eintragen.

„ECONNREFUSED“ oder Datenbankverbindung schlägt fehl

Directus startet vor PostgreSQL. Healthcheck und depends_on mit condition: service_healthy wie in Schritt 3 setzen.

Admin-Login nach erstem Start schlägt fehl

ADMIN_EMAIL/ADMIN_PASSWORD gelten nur beim ersten Datenbanksetup, spätere Änderungen in der .env wirken nicht. Passwort in der Oberfläche ändern oder „Passwort vergessen“ nutzen.

Uploads nach Container-Neustart weg

Der Mount ./uploads:/directus/uploads fehlt. Eintrag prüfen, Container neu erstellen.

„Public URL mismatch“ bei Datei-URLs oder OAuth

PUBLIC_URL weicht von der externen Adresse ab (etwa http statt https). Exakt setzen, Container neu starten.

Hohe Last oder 403 durch Healthcheck

/server/health prüft alle Abhängigkeiten und verlangt eine Anmeldung. Für Healthchecks /server/ping verwenden.

Extension lädt nicht / „Cannot find module“

Der Mount ./extensions:/directus/extensions fehlt oder die Extension liegt im falschen Unterordner. Mount und Verzeichnisstruktur prüfen.

Grenzen der Core-Stufe erreicht

Ohne Lizenzschlüssel greifen die Grenzen für Nutzerplätze, Collections und Flows (siehe Schritt 2). Lösung: Lizenzschlüssel einspielen oder, sofern berechtigt, das Open Innovation Grant beantragen.

Häufige Fragen

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

Ja. Directus liest das Schema aus und erzeugt API-Endpunkte für die vorhandenen Tabellen, ohne Tabellen oder Datenzeilen zu verändern. Es ergänzt nur eigene Systemtabellen mit dem Präfix directus_. Legen Sie trotzdem vorher ein Backup an.

Welche Datenbanken werden unterstützt?

Laut Dokumentation die LTS-Versionen von PostgreSQL, MySQL, MariaDB, SQLite, MS SQL Server, CockroachDB und OracleDB. SQLite eignet sich für lokale Tests ohne separaten Container (DB_CLIENT=sqlite3, DB_FILENAME=/directus/database.db). DB_CLIENT akzeptiert pg (oder postgres), mysql, oracledb, mssql, sqlite3 und cockroachdb.

Ist Redis Pflicht?

Nein. Kleine Instanzen laufen ohne Cache; bei mehreren gleichzeitigen Nutzern verkürzt Redis die Antwortzeiten.

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

Ja. Das Image directus/directus gibt es für linux/arm64; Docker wählt die passende Variante automatisch, die Compose-Datei bleibt gleich.

Wie aktualisiere ich Directus auf eine neue Version?

Backup per pg_dump, Image-Tag anpassen, docker compose pull && docker compose up -d. Details in Schritt 8.

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

Das docker-compose.yml im GitHub-Repository startet alle unterstützten Datenbanken gleichzeitig und dient nur der Entwicklung von Directus. Für den eigenen Betrieb ist die Compose-Vorlage in der Dokumentation unter directus.com/docs/self-hosting/deploying maßgeblich.

Fazit

Directus macht aus einer SQL-Datenbank ohne Schemaänderung und eigenen Code eine REST- und GraphQL-API mit Admin-Oberfläche; der Stack aus drei Containern ist überschaubar. Prüfen Sie vor dem Produktivbetrieb die Lizenzgrenzen der Core-Stufe und setzen Sie einen kryptografisch sicheren SECRET.

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
  7. Docker Compose mit Secrets, Healthchecks und Non-Root absichern

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