Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Datenbanken 14.08.2026 · 9 min Lesezeit Geprüft 11.10.2026

Hasura mit Docker installieren: sofortige Echtzeit-GraphQL-API für bestehende Datenbanken

Hasura erzeugt aus einer PostgreSQL-Datenbank eine GraphQL-API mit Queries, Mutations und Subscriptions. Die Anleitung zeigt Hasura v2.51 mit Docker Compose, Absicherung per Admin-Secret und die Anbindung Ihrer Datenbank.

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: Hasura mit Docker installieren, GraphQL, Echtzeit, Datenbank

Eine GraphQL-API über eine bestehende Datenbank bedeutet normalerweise viel Handarbeit: Resolver, Typdefinitionen und Berechtigungslogik. Hasura GraphQL Engine erzeugt diese API aus dem Datenbankschema. Sie verbinden die Engine per Verbindungs-URL mit einer PostgreSQL-Datenbank und erhalten Queries, Mutations und Subscriptions ohne eigenen Backend-Code. Diese Anleitung nutzt Version v2.51.0 und Docker Compose.

Voraussetzungen

  • Docker Engine >= 20.10 und Docker Compose v2 (nötig für condition: service_healthy). Installation: Docker und Docker Compose auf Linux installieren.
  • Linux-Host, VM oder NAS mit laufendem Docker-Daemon, x86_64 oder arm64.
  • Freie Ports 8080 (Console und GraphQL-Endpoint) und optional 8081 (Data Connector Agent).
  • 2 CPU-Kerne und mindestens 2 GB RAM; der Stack belegt im Leerlauf ca. 400 bis 600 MB.
  • Zugang zu Docker Hub für den Image-Pull.
  • Für die Produktion ein Reverse Proxy mit TLS.

Schritt 1: Eckdaten und Stack-Überblick

Die Tabelle nennt die Eckdaten des Stacks:

KomponenteWert
Image (Engine)hasura/graphql-engine:v2.51.0
Image (Connector)hasura/graphql-data-connector:v2.51.0
Image (Datenbank)postgres:15
Port Hasura8080 (Web-Console, GraphQL, REST, Health)
Port Connector8081 (intern; nur bei Bedarf exponieren)
Volumedb_data → PostgreSQL-Datenpersistenz
Metadaten-Pflicht-EnvHASURA_GRAPHQL_METADATA_DATABASE_URL
Admin-Secret-EnvHASURA_GRAPHQL_ADMIN_SECRET (Pflicht in Produktion)

postgres speichert die Hasura-Metadaten (Berechtigungen, Relationships, Actions) und optional Ihre Anwendungsdaten. graphql-engine ist die API auf Port 8080. data-connector-agent brauchen Sie nur für Nicht-Postgres-Datenbanken (MySQL 8, Oracle, Snowflake, Athena, MariaDB).

docker --version und docker compose version antworten ohne Fehler (mindestens Docker 20.10, Compose 2.x).

$ docker --version
$ docker compose version

Schritt 2: Projektordner anlegen

Alle Dateien des Stacks liegen in einem Verzeichnis, hier unter /opt/:

$ mkdir -p /opt/hasura
$ cd /opt/hasura
$ ls -la /opt/hasura

Das Verzeichnis existiert.

Schritt 3: .env-Datei mit Secrets anlegen

Schreiben Sie Secrets nicht in die compose.yaml, sondern in eine .env-Datei im Projektordner:

# /opt/hasura/.env

# Passwort für den lokalen PostgreSQL-Container
POSTGRES_PASSWORD=einSicheresPasswortHier

# Admin-Secret für Hasura, sichert alle Endpoints ab
# Mindestens 32 zufällige Zeichen, z. B. per: openssl rand -hex 32
HASURA_ADMIN_SECRET=ersetzen-durch-ein-langes-zufaelliges-geheimnis

Schützen Sie die Datei mit chmod 600 /opt/hasura/.env.

Das Admin-Secret sichert die Console und den /v1/graphql-Endpoint. Ohne Secret ist alles ohne Authentifizierung erreichbar, auch in Entwicklungsumgebungen.

$ stat -c "%a %n" /opt/hasura/.env

Ausgabe: 600 /opt/hasura/.env.

Schritt 4: compose.yaml erstellen

Die compose.yaml enthält alle drei Services. Die Healthchecks sorgen dafür, dass Hasura erst startet, wenn PostgreSQL bereit ist:

services:
  postgres:
    image: postgres:15
    restart: always
    volumes:
      - db_data:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgrespassword}
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

  graphql-engine:
    image: hasura/graphql-engine:v2.51.0
    ports:
      - "8080:8080"
    restart: always
    depends_on:
      postgres:
        condition: service_healthy
      data-connector-agent:
        condition: service_healthy
    environment:
      HASURA_GRAPHQL_METADATA_DATABASE_URL: postgres://postgres:${POSTGRES_PASSWORD:-postgrespassword}@postgres:5432/postgres
      PG_DATABASE_URL: postgres://postgres:${POSTGRES_PASSWORD:-postgrespassword}@postgres:5432/postgres
      HASURA_GRAPHQL_ENABLE_CONSOLE: "true"
      HASURA_GRAPHQL_DEV_MODE: "true"
      HASURA_GRAPHQL_ADMIN_SECRET: ${HASURA_ADMIN_SECRET:-changeme_in_production}
      HASURA_GRAPHQL_ENABLED_LOG_TYPES: startup, http-log, webhook-log, websocket-log, query-log
      HASURA_GRAPHQL_METADATA_DEFAULTS: '{"backend_configs":{"dataconnector":{"athena":{"uri":"http://data-connector-agent:8081/api/v1/athena"},"mariadb":{"uri":"http://data-connector-agent:8081/api/v1/mariadb"},"mysql8":{"uri":"http://data-connector-agent:8081/api/v1/mysql"},"oracle":{"uri":"http://data-connector-agent:8081/api/v1/oracle"},"snowflake":{"uri":"http://data-connector-agent:8081/api/v1/snowflake"}}}}'

  data-connector-agent:
    image: hasura/graphql-data-connector:v2.51.0
    restart: always
    ports:
      - "8081:8081"
    environment:
      QUARKUS_LOG_LEVEL: ERROR
      QUARKUS_OPENTELEMETRY_ENABLED: "false"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8081/api/v1/athena/health"]
      interval: 5s
      timeout: 10s
      retries: 5
      start_period: 5s

volumes:
  db_data:

Das db_data-Volume hält die Daten dauerhaft.

Reine PostgreSQL-Setups: Entfernen Sie den Service data-connector-agent und seine depends_on-Bedingung in graphql-engine.

$ docker compose -f /opt/hasura/compose.yaml config --quiet && echo "Syntax OK"

Ausgabe: Syntax OK.

Schritt 5: Stack starten

Starten Sie den Stack im Hintergrund:

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

Der erste Start lädt die Images (Engine ca. 175 MB) und dauert je nach Verbindung zwei bis fünf Minuten.

$ cd /opt/hasura
$ docker compose ps

Alle drei Services laufen, PostgreSQL und der Data-Connector-Agent zusätzlich mit (healthy); die Engine hat in dieser Datei keinen eigenen Healthcheck:

NAME                         IMAGE                                        STATUS
hasura-postgres-1            postgres:15                                  Up X minutes (healthy)
hasura-graphql-engine-1      hasura/graphql-engine:v2.51.0               Up X minutes
hasura-data-connector-agent-1 hasura/graphql-data-connector:v2.51.0     Up X minutes (healthy)

Bei restarting oder exited helfen die Logs:

$ docker compose logs graphql-engine --tail=50

Schritt 6: Healthcheck und ersten API-Aufruf testen

Der Endpoint /healthz eignet sich auch für Monitoring und Load-Balancer:

$ curl -s http://localhost:8080/healthz

Ausgabe: OK

Testen Sie anschließend den GraphQL-Endpoint direkt, mit dem Admin-Secret im Header:

curl -s -X POST http://localhost:8080/v1/graphql \
  -H "Content-Type: application/json" \
  -H "x-hasura-admin-secret: ersetzen-durch-ein-langes-zufaelliges-geheimnis" \
  -d '{"query": "{ __typename }"}'

Ausgabe: {"data":{"__typename":"query_root"}}

Beide curl-Aufrufe antworten ohne Fehler. HTTP 401 beim zweiten Aufruf bedeutet, dass das Admin-Secret nicht eingelesen wurde; prüfen Sie es mit docker compose exec graphql-engine env | grep HASURA_GRAPHQL_ADMIN_SECRET.

Schritt 7: Web-Console öffnen und erste Tabelle anlegen

Öffnen Sie im Browser die Hasura-Console:

http://localhost:8080/console

Die Console fragt nach dem Admin-Secret aus Ihrer .env-Datei.

Datenbank verbinden und erste Tabelle anlegen:

  1. Klicken Sie auf Data und dann Connect Database. Die Variable PG_DATABASE_URL registriert die Datenbank nicht automatisch, die Liste der Datenquellen ist nach dem ersten Start leer. Wählen Sie PostgreSQL, als Namen default und die Option „Environment Variable“ mit dem Wert PG_DATABASE_URL. So steht das Passwort nicht in den Metadaten.
  2. Klicken Sie auf default und dann Create Table. Legen Sie eine Tabelle users mit den Spalten id (Integer, PK, autoincrement) und name (Text) an.
  3. Öffnen Sie den Tab API (GraphiQL), Hasura hat Queries und Mutations erzeugt:
query {
  users {
    id
    name
  }
}

GraphiQL zeigt für die neue Tabelle eine leere Liste []. Die Meldung „field 'users' not found in type: 'query_root'“ bedeutet, dass die Tabelle noch nicht „tracked“ ist: Klicken Sie im Data-Tab neben der Tabelle auf „Track“.

Schritt 8: Echtzeit-Subscriptions testen

Hasura führt Subscriptions als Live Queries aus: Die Engine fragt die Datenbank per Polling ab (Standard: jede Sekunde) und sendet nur geänderte Ergebnisse an die Clients.

Öffnen Sie in GraphiQL zwei Browser-Tabs. Im ersten läuft eine Subscription:

subscription {
  users {
    id
    name
  }
}

Im zweiten fügen Sie einen Datensatz per Mutation ein:

mutation {
  insert_users_one(object: { name: "Alice" }) {
    id
    name
  }
}

Das Subscription-Tab zeigt den neuen Datensatz nach etwa einer Sekunde ohne Seiten-Reload. Damit funktionieren auch die WebSocket-Verbindungen.

Schritt 9: Externe Datenbank anbinden (optional)

Hasura liest von einer vorhandenen Datenbank nur das Schema über INFORMATION_SCHEMA; die Metadaten landen in der Metadata-Datenbank.

Klicken Sie auf Data, Connect Database und wählen Sie den Datenbanktyp. Für PostgreSQL tragen Sie die Verbindungs-URL ein:

postgres://benutzer:passwort@host:5432/datenbankname

Für MySQL, Oracle, Snowflake, Athena oder MariaDB vermittelt der data-connector-agent, der im Stack bereits konfiguriert ist. Wählen Sie den passenden Connector-Typ.

Der Datenbankbenutzer braucht mindestens USAGE auf dem Schema und SELECT auf den Tabellen, für Event-Trigger zusätzlich TRIGGER.

Die Datenquelle erscheint im Data-Tab. Nach Track All tauchen die Tabellen im API-Tab als Queries auf.

Schritt 10: Berechtigungen konfigurieren (Row-Level Security)

Berechtigungen legen Sie je Tabelle im Tab Permissions fest:

  1. Rolle anlegen: zum Beispiel user.
  2. Row-Level-Filter: ein JSON-Filter bestimmt, welche Zeilen die Rolle sieht, zum Beispiel {"owner_id": {"_eq": "X-Hasura-User-Id"}}.
  3. Column-Level: Sie wählen die sichtbaren oder schreibbaren Spalten.

Für JWT-Authentifizierung (Auth0, Keycloak) setzen Sie HASURA_GRAPHQL_JWT_SECRET im Block environment der compose.yaml.

Simulieren Sie die Rolle user mit Admin-Secret, Rollen- und Benutzer-Header. Hasura wendet dann den Filter dieser Rolle an:

curl -s -X POST http://localhost:8080/v1/graphql \
  -H "Content-Type: application/json" \
  -H "x-hasura-admin-secret: ersetzen-durch-ein-langes-zufaelliges-geheimnis" \
  -H "x-hasura-role: user" \
  -H "x-hasura-user-id: 1" \
  -d '{"query": "{ users { id name } }"}'

Ausgabe: nur Zeilen, deren owner_id 1 ist, sonst eine leere Liste. Endnutzer authentifizieren sich per JWT oder Webhook.

Schritt 11: Produktion absichern

Für den Produktionsbetrieb ändern Sie im Service graphql-engine der compose.yaml diese Werte im Block environment. Eine .env-Datei überschreibt sie nicht, sie liefert nur Werte für ${…}-Platzhalter:

# Console deaktivieren, Schema-Änderungen nur per CLI/Migrations
HASURA_GRAPHQL_ENABLE_CONSOLE: "false"
# Dev-Mode aus: keine internen Fehlerdetails in API-Antworten
HASURA_GRAPHQL_DEV_MODE: "false"
# query-log entfällt (sehr großes Log-Volumen unter Last)
HASURA_GRAPHQL_ENABLED_LOG_TYPES: startup, http-log, webhook-log, websocket-log
# CORS auf erlaubte Domains einschränken
HASURA_GRAPHQL_CORS_DOMAIN: https://meine-app.example.com

Für TLS stellen Sie Hasura hinter einen Reverse Proxy, zum Beispiel Traefik als Docker-Reverse-Proxy mit automatischem HTTPS. Alternativ eignet sich Caddy als Reverse Proxy einrichten.

Entfernen Sie in Produktion das ports-Mapping des Services data-connector-agent, damit Port 8081 nicht auf dem Host erreichbar ist.

$ cd /opt/hasura
$ docker compose up -d
$ curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8080/console

Nach dem Neustart antwortet /console mit HTTP 404. Der /v1/graphql-Endpoint bleibt erreichbar, nur mit Admin-Secret oder gültigem JWT.

Schritt 12: Updates und Backup

Für ein Update ändern Sie den Image-Tag beider Hasura-Images in der compose.yaml und führen Sie aus:

$ cd /opt/hasura
$ docker compose pull
$ docker compose up -d

Update von v2.49 auf v2.51: Laut Release Notes gibt es keinen manuellen Migrationsschritt, die Engine aktualisiert ihren Katalog beim Start. Im Test lief eine Installation mit v2.49.2 und einer getrackten Tabelle nach dem Tagwechsel auf v2.51.0 ohne Eingriff weiter. Beachten Sie: Seit v2.49.4 wertet Hasura den Header X-Hasura-Access-Key nicht mehr aus, Clients senden x-hasura-admin-secret. Ab v2.50.0 müssen Event-Trigger-Namen aus Buchstaben, Ziffern, Unterstrich und Bindestrich bestehen; abweichende Namen laufen weiter, müssen aber vor dem nächsten replace_metadata korrigiert werden.

Sichern müssen Sie das db_data-Volume: Es enthält die Anwendungsdaten und die Hasura-Metadaten (Berechtigungen, Relationships, Actions, Event-Trigger). Für konsistente Backups dient pg_dump, siehe PostgreSQL pg_dump und pg_restore: Backup und Migration.

Warnung: Löschen Sie das db_data-Volume nie ohne vorheriges hasura metadata export (Hasura CLI), sonst verlieren Sie Berechtigungen, Relationships und Actions.

$ docker compose ps
$ curl -s http://localhost:8080/healthz

Alle Services laufen (PostgreSQL und Connector healthy), /healthz antwortet mit OK.

Troubleshooting / Typische Fehler

„could not connect to server“ beim Start

graphql-engine startet vor PostgreSQL. Ursache ist ein fehlender healthcheck im Service postgres. Die compose.yaml dieser Anleitung enthält ihn samt depends_on: condition: service_healthy.

HTTP 401 bei allen API-Aufrufen

Der Header x-hasura-admin-secret: ersetzen-durch-ein-langes-zufaelliges-geheimnis fehlt im Request.

„Metadata inconsistency“ nach Neustart

Das db_data-Volume wurde gelöscht oder falsch gemountet. Prüfen Sie mit docker volume ls | grep db_data.

Data Connector Agent nicht erreichbar

graphql-engine startet, bevor der Agent healthy ist. Erhöhen Sie den start_period des Agent-Healthchecks, auf ARM-Systemen auf 15 bis 30 Sekunden.

CORS-Fehler im Browser

HASURA_GRAPHQL_CORS_DOMAIN enthält nicht die exakte Origin der Frontend-App. Geben Sie Schema und Port an, zum Beispiel https://app.example.com:3000.

„permission denied“ bei externer Datenbank

Dem Datenbankbenutzer fehlen die Rechte aus Schritt 9.

Subscriptions reagieren verzögert

Hasura fragt die Datenbank per Polling ab. Das Intervall stellt HASURA_GRAPHQL_LIVE_QUERIES_MULTIPLEXED_REFETCH_INTERVAL ein (Standard 1000 ms).

Häufige Fragen

Kann ich Hasura mit einer bereits vorhandenen Datenbank verbinden, ohne Daten zu verlieren?

Ja. Hasura ändert weder Tabellen noch Daten der Anwendungsdatenbank. Es liest das Schema über INFORMATION_SCHEMA und speichert seine Metadaten in der separaten Metadata-Datenbank. Sie fügen die Datenbank als neue Datenquelle in der Console hinzu.

Was ist der Unterschied zwischen Hasura v2 und Hasura v3 (DDN)?

Hasura v2 ist die etablierte Version für Self-Hosted-Docker-Deployments und wird gepflegt. Hasura v3 (DDN) hat eine neue Architektur mit Supergraph und anderem Workflow. Diese Anleitung beschreibt v2.

Benötige ich den data-connector-agent für reine PostgreSQL-Setups?

Nein, er wird nur für Nicht-Postgres-Datenbanken benötigt. Das Entfernen beschreibt Schritt 4.

Wie sichere ich Hasura für den Produktionsbetrieb ab?

Admin-Secret setzen, Console und Dev-Mode abschalten, CORS einschränken, Endnutzer per JWT oder Webhook authentifizieren, TLS per Reverse Proxy und Port 8081 nicht veröffentlichen. Die Einstellungen stehen in Schritt 11.

Wie funktionieren automatische Datenbankmigrationen mit Hasura?

Die Image-Variante cli-migrations-v3 führt beim Start SQL-Migrationen aus dem Verzeichnis /hasura-migrations aus und wendet Metadaten aus /hasura-metadata an. Sie erstellen Migrationen mit hasura migrate create und versionieren sie in Git. Das macht Deployments reproduzierbar.

Kann Hasura als Read-Only-API vor einer Produktionsdatenbank betrieben werden?

Ja. Legen Sie einen Datenbankbenutzer mit ausschließlich SELECT-Rechten an, tragen Sie ihn in PG_DATABASE_URL ein und vergeben Sie nur Query-Berechtigungen.

Fazit

Hasura erzeugt aus einer PostgreSQL-Datenbank in wenigen Minuten eine GraphQL-API. Im Betrieb zählen ein gesetztes Admin-Secret, abgeschaltete Console, TLS per Reverse Proxy und die Sicherung des db_data-Volumes.

Weiterführende Anleitungen und Quellen

  1. PostgreSQL pg_dump und pg_restore: Backup und Migration per Kommandozeile
  2. Traefik als Docker-Reverse-Proxy mit automatischem HTTPS einrichten
  3. Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only für den Produktivbetrieb
  4. Directus mit Docker installieren: Verwandelt jede bestehende SQL-Datenbank in eine API: Alternative für REST-first-Ansätze.

Offizielle Quellen: Hasura Getting Started mit Docker | Hasura auf GitHub | Hasura Docker Hub Image