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

Apache Superset mit Docker: eigenes Image mit PostgreSQL, Redis und Celery

Apache Superset 6.1 mit Docker Compose betreiben: eigenes Image mit psycopg2, superset_config.py für PostgreSQL, Redis und Celery, Init-Container, Healthchecks, Backup mit getesteter Rücksicherung.

Geprüft am 30.09.2026 · für Apache Superset 6.1.0

WerbelinksMit * 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

Besprechungstisch mit ausgedruckten farbigen Balken-, Linien- und Ringdiagrammen ohne Beschriftung, daneben zugeklapptes Notebook, Kaffeetasse und Stift

Apache Superset ist eine quelloffene Plattform für Datenanalyse und Dashboards: Sie verbinden Datenbanken wie PostgreSQL, MySQL oder SQL Server, bauen Diagramme per Klick und fragen Daten im SQL-Editor „SQL Lab“ ab. Für den Betrieb mit Docker stellt das Projekt das Image apache/superset bereit. Dieses Standard-Image (Preset „lean“) enthält aber bewusst keine Datenbanktreiber, auch nicht für die eigene Metadaten-Datenbank, und keine Konfiguration. Wer es mit PostgreSQL und Redis betreiben will, braucht deshalb ein kleines eigenes Image und eine superset_config.py. Genau das baut diese Anleitung für Superset 6.1.0 auf, getestet mit Web-Server, Celery-Worker und Scheduler.

Voraussetzungen

  • Server: Linux mit Docker Engine und Compose-Plugin v2, x86_64 oder ARM64 (das Image gibt es für beide).
  • RAM: Im Test belegte der Stack im Leerlauf rund 820 MB (Worker 380 MB, Web 193 MB, Beat 189 MB, PostgreSQL 59 MB). Für Abfragen auf größere Datenmengen und mehrere Nutzer planen Sie 4 GB, für viele parallele Dashboards 8 GB.
  • CPU: 2 Kerne.
  • Speicher: etwa 2 GB für die Images (eigenes Superset-Image 1,3 GB, PostgreSQL 650 MB) plus Datenbank und Logs.
  • Domain und Reverse Proxy mit HTTPS für den Zugriff im Netz.

Ein Hinweis zur Einordnung: Die offiziellen Compose-Dateien im Superset-Repository sind laut Doku für Entwicklung gedacht, für Produktion empfiehlt das Projekt Kubernetes. Der hier gezeigte eigene Stack eignet sich für einen einzelnen Server im Team oder in der Abteilung. Grundlagen zu Docker liefert Docker und Docker Compose auf Linux installieren.

Schritt 1: Projektordner und eigenes Image

Die Superset-Doku zu den Docker-Builds ist eindeutig: Das lean-Image enthält keine Treiber, weder für Analyse-Datenbanken noch für die Metadaten-Datenbank; Betreiber sollen es erweitern. Im Test bestätigte sich das: import psycopg2 scheitert im Original-Image mit ModuleNotFoundError: No module named 'psycopg2'.

mkdir -p /opt/superset && cd /opt/superset

Legen Sie das Dockerfile an. Das Muster mit uv pip in der virtuellen Umgebung stammt aus der offiziellen Beispiel-Datei:

FROM apache/superset:6.1.0
USER root
RUN . /app/.venv/bin/activate && uv pip install psycopg2-binary
USER superset

Treiber für Ihre Datenquellen ergänzen Sie in derselben Zeile, etwa pymssql für SQL Server oder mysqlclient für MySQL. Die Doku listet je Datenbank das passende Paket.

Verifizieren: Nach dem Build (Schritt 4) liefert docker run --rm --entrypoint python superset-lokal:6.1.0 -c "import psycopg2;print(psycopg2.__version__)" eine Versionsnummer; im Test 2.9.13.

Schritt 2: superset_config.py schreiben

Superset liest seine Einstellungen aus einem Python-Modul. Das Image setzt PYTHONPATH=/app/pythonpath, dort liegt aber keine Datei. Im Test zeigte Superset ohne eigene Konfiguration als Metadaten-Datenbank sqlite:////app/superset_home/superset.db, auch wenn Variablen wie DATABASE_HOST gesetzt waren. Diese Variablen wertet nur die Konfigurationsdatei der Entwicklungsumgebung aus, die im Image nicht enthalten ist.

import os
from celery.schedules import crontab

SECRET_KEY = os.environ["SUPERSET_SECRET_KEY"]

SQLALCHEMY_DATABASE_URI = (
    f"postgresql+psycopg2://{os.environ['POSTGRES_USER']}:{os.environ['POSTGRES_PASSWORD']}"
    f"@db:5432/{os.environ['POSTGRES_DB']}"
)

REDIS_URL = "redis://redis:6379"
CACHE_CONFIG = {
    "CACHE_TYPE": "RedisCache",
    "CACHE_DEFAULT_TIMEOUT": 300,
    "CACHE_KEY_PREFIX": "superset_",
    "CACHE_REDIS_URL": f"{REDIS_URL}/1",
}
DATA_CACHE_CONFIG = CACHE_CONFIG
FILTER_STATE_CACHE_CONFIG = {**CACHE_CONFIG, "CACHE_KEY_PREFIX": "superset_filter_"}
EXPLORE_FORM_DATA_CACHE_CONFIG = {**CACHE_CONFIG, "CACHE_KEY_PREFIX": "superset_explore_"}

class CeleryConfig:
    broker_url = f"{REDIS_URL}/0"
    result_backend = f"{REDIS_URL}/0"
    imports = ("superset.sql_lab", "superset.tasks.scheduler")
    worker_prefetch_multiplier = 1
    task_acks_late = False
    beat_schedule = {
        "reports.scheduler": {"task": "reports.scheduler", "schedule": crontab(minute="*", hour="*")},
        "reports.prune_log": {"task": "reports.prune_log", "schedule": crontab(minute=10, hour=0)},
    }

CELERY_CONFIG = CeleryConfig
ENABLE_PROXY_FIX = True

Die Datei holt Geheimnisse aus Umgebungsvariablen, statt sie selbst zu enthalten. Die Cache-Einträge folgen der Doku „Caching“, die CeleryConfig der Doku „Async Queries via Celery“ und der Entwicklungskonfiguration des Projekts. ENABLE_PROXY_FIX sorgt dafür, dass Superset hinter einem Reverse Proxy die weitergereichten Header auswertet.

Verifizieren: python3 -m py_compile superset_config.py läuft ohne Ausgabe durch. Nach dem Start (Schritt 4) meldet jedes Superset-Log Loaded your LOCAL configuration at [/app/superset_config.py].

Schritt 3: .env und compose.yaml

printf 'SUPERSET_SECRET_KEY=%s\nPOSTGRES_DB=superset\nPOSTGRES_USER=superset\nPOSTGRES_PASSWORD=%s\nADMIN_PASSWORD=%s\n' \
  "$(openssl rand -base64 42 | tr -d '\n')" "$(openssl rand -hex 16)" "$(openssl rand -hex 12)" > .env
chmod 600 .env

openssl rand -base64 42 ist die Empfehlung der Superset-Doku für den SECRET_KEY. Er signiert Sitzungen und verschlüsselt gespeicherte Datenbank-Passwörter; ändern Sie ihn später nur über den dokumentierten Weg mit PREVIOUS_SECRET_KEY und superset re-encrypt-secrets.

x-superset: &superset
  build: .
  image: superset-lokal:6.1.0
  env_file: .env
  environment:
    SUPERSET_CONFIG_PATH: /app/superset_config.py
  volumes:
    - ./superset_config.py:/app/superset_config.py:ro
  depends_on:
    db:
      condition: service_healthy
    redis:
      condition: service_started
  restart: unless-stopped

services:
  db:
    image: postgres:17
    env_file: .env
    volumes:
      - db:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
      interval: 5s
      retries: 10
    restart: unless-stopped
  redis:
    image: redis:7.4-alpine
    volumes:
      - redis:/data
    restart: unless-stopped
  superset-init:
    <<: *superset
    command:
      - sh
      - -c
      - superset db upgrade && superset fab create-admin --username admin --firstname Admin --lastname User --email admin@firma.de --password "$$ADMIN_PASSWORD" && superset init
    restart: "no"
  superset:
    <<: *superset
    ports:
      - "127.0.0.1:8088:8088"
    depends_on:
      superset-init:
        condition: service_completed_successfully
  superset-worker:
    <<: *superset
    command: ["celery", "--app=superset.tasks.celery_app:app", "worker", "-O", "fair", "-l", "INFO", "--concurrency=2"]
    healthcheck:
      test: ["CMD-SHELL", "celery -A superset.tasks.celery_app:app inspect ping -d celery@$$HOSTNAME"]
      interval: 60s
      timeout: 20s
    depends_on:
      superset-init:
        condition: service_completed_successfully
  superset-beat:
    <<: *superset
    command: ["celery", "--app=superset.tasks.celery_app:app", "beat", "--pidfile", "/tmp/celerybeat.pid", "-l", "INFO", "-s", "/tmp/celerybeat-schedule"]
    healthcheck:
      disable: true
    depends_on:
      superset-init:
        condition: service_completed_successfully

volumes:
  db:
  redis:
DienstImageAufgabe
supersetsuperset-lokal:6.1.0 (aus apache/superset:6.1.0)Weboberfläche und API, Port 8088
superset-workerdasselbeCelery-Worker für asynchrone Abfragen und Berichte
superset-beatdasselbeZeitplaner, genau eine Instanz
superset-initdasselbeMigration, Admin, Rollen; beendet sich
dbpostgres:17Metadaten-Datenbank
redisredis:7.4-alpineBroker (DB 0), Cache (DB 1)

Zwei Details stammen direkt aus dem Test. Der Befehl des Init-Containers steht als einzeilige Liste: Als mehrzeiliger YAML-Block (>) mit eingerückter Fortsetzungszeile wurde der Zeilenumbruch erhalten, und die Shell meldete sh: 3: --email: not found. Außerdem prüft der Healthcheck des Images Port 8088; Worker und Beat öffnen diesen Port nicht und stünden sonst dauerhaft auf unhealthy. Laut Doku darf Beat nur einmal laufen, sonst werden Berichte doppelt verschickt.

Verifizieren: docker compose config -q gibt nichts aus, docker compose config | grep -A2 ports zeigt host_ip: 127.0.0.1.

Schritt 4: Bauen und starten

docker compose build
docker compose up -d
docker compose logs superset-init | tail -5

Im Test lief die Migration in wenigen Sekunden durch, das Init-Log endete mit Admin User admin created.. Web, Worker und Beat starteten danach, der Web-Container war nach rund 30 Sekunden healthy. Der Worker meldete Connected to redis://redis:6379/0 und celery@… ready., der Scheduler nach einer Minute Sending due task reports.scheduler.

Verifizieren: docker compose ps -a zeigt superset-init als Exited (0), superset und superset-worker als healthy. curl -s http://127.0.0.1:8088/health liefert OK. In der Datenbank prüfen Sie, dass Superset wirklich PostgreSQL nutzt: docker compose exec db psql -U superset -d superset -tAc "select username from ab_user;" liefert admin.

Schritt 5: Anmelden und erste Datenquelle anbinden

Öffnen Sie Superset per SSH-Tunnel (ssh -L 8088:127.0.0.1:8088 benutzer@server) unter http://localhost:8088 und melden Sie sich mit admin und dem ADMIN_PASSWORD aus der .env an. Ändern Sie das Passwort anschließend im Profil. Unter Settings > Database Connections fügen Sie eine Datenquelle hinzu; die Verbindungszeichenfolge folgt dem SQLAlchemy-Schema, etwa postgresql+psycopg2://leser:passwort@db-host:5432/warenwirtschaft. Verwenden Sie dafür ein Datenbankkonto mit reinen Leserechten. Asynchrone Abfragen über die Worker nutzt SQL Lab erst, wenn Sie in den Einstellungen der Datenbank „Asynchronous Query Execution“ aktivieren.

Verifizieren: Die Anmeldung per API liefert ein Token: curl -s -X POST http://127.0.0.1:8088/api/v1/security/login -H 'Content-Type: application/json' -d '{"username":"admin","password":"…","provider":"db"}'. Mit falschem Passwort antwortet die API mit 401, beides so im Test. „Test Connection“ im Dialog der Datenquelle meldet Erfolg.

Schritt 6: Reverse Proxy und HTTPS

Superset selbst spricht nur HTTP. Die Doku empfiehlt TLS am Reverse Proxy oder Load Balancer und den Endpunkt /health für Zustandsprüfungen. Mit Caddy auf dem Host:

bi.firma.de {
    reverse_proxy 127.0.0.1:8088
}

Weil ENABLE_PROXY_FIX = True gesetzt ist, übernimmt Superset X-Forwarded-Proto und erzeugt korrekte HTTPS-Links. Details zu Caddy stehen in Caddy als Reverse Proxy einrichten.

Verifizieren: curl -s https://bi.firma.de/health liefert OK, curl -sI https://bi.firma.de/ leitet auf eine HTTPS-Adresse unter /superset/welcome/ bzw. zur Anmeldung weiter.

Schritt 7: Backup und Update

Alle Dashboards, Diagramme, Nutzer und gespeicherten Verbindungen liegen in der Metadaten-Datenbank. Die Doku weist darauf hin, dass sie gesichert werden muss. Sichern Sie außerdem .env (mit dem SECRET_KEY, ohne den gespeicherte Datenbank-Passwörter unlesbar werden), superset_config.py, Dockerfile und compose.yaml.

docker compose exec -T db pg_dump -U superset -Fc superset > superset-$(date +%F).dump
# Rücksicherung in eine Testdatenbank prüfen
docker compose exec -T db psql -U superset -d postgres -c 'CREATE DATABASE restoretest;'
docker compose exec -T db pg_restore -U superset -d restoretest --no-owner < superset-$(date +%F).dump
docker compose exec -T db psql -U superset -d restoretest -tAc 'select username from ab_user;'
docker compose exec -T db psql -U superset -d postgres -c 'DROP DATABASE restoretest;'

Für ein Update lesen Sie die Datei UPDATING.md und die Release Notes, sichern, ändern das Tag im Dockerfile und führen docker compose build --pull und docker compose up -d aus. Der Init-Container migriert die Datenbank beim nächsten Start.

Verifizieren: pg_restore endet mit Exit-Code 0, die Abfrage liefert admin; so im Test.

Typische Fehler

  • ModuleNotFoundError: No module named 'psycopg2': Das Original-Image wird verwendet. Eigenes Image aus Schritt 1 bauen und in der Compose-Datei verwenden.
  • Dashboards fehlen, nachdem der Container neu erstellt wurde: Superset nutzt SQLite im Container, weil keine superset_config.py geladen wird. Log auf Loaded your LOCAL configuration prüfen, SUPERSET_CONFIG_PATH und Mount kontrollieren.
  • sh: 3: --email: not found im Init-Container: Mehrzeiliger Befehl zerfällt in einzelne Shell-Zeilen. Befehl als Liste wie in Schritt 3 schreiben.
  • Worker und Beat dauerhaft unhealthy: Der Image-Healthcheck prüft Port 8088. Eigenen Healthcheck setzen oder abschalten.
  • Start bricht mit Hinweis auf fehlenden oder unsicheren SECRET_KEY ab: Seit Version 2.1 verlangt Superset einen eigenen Schlüssel. Wert in .env prüfen.

Häufige Fragen

Warum nicht einfach das Image mit „-dev“?

Die -dev-Varianten enthalten laut Doku gängige Treiber, einen Headless-Browser und Root-Rechte. Sie sind für Entwicklung gedacht. Für den Betrieb empfiehlt das Projekt, das lean-Image um genau die benötigten Pakete zu erweitern.

Brauche ich Worker und Beat überhaupt?

Für Dashboards und kurze Abfragen nicht. Worker braucht es für lang laufende Abfragen in SQL Lab und für Alerts und Reports, Beat für deren Zeitplan. Wer darauf verzichtet, lässt beide Dienste weg; Redis bleibt als Cache sinnvoll.

Kann ich E-Mail-Berichte mit Screenshots verschicken?

Dafür braucht das Image zusätzlich Playwright und Chromium sowie SMTP-Einstellungen. Die offizielle Beispiel-Datei zu den Docker-Builds zeigt die Installation. Das ist in dieser Anleitung nicht enthalten und nicht getestet.

Ist Superset eine Alternative zu Metabase?

Beide decken Dashboards und Ad-hoc-Abfragen ab. Superset richtet sich stärker an Nutzer mit SQL-Kenntnissen und bietet viele Diagrammtypen, Metabase an Fachanwender mit geführten Fragen. Einen Einstieg in Metabase gibt Metabase auf dem Synology NAS.

Fazit

Superset läuft zuverlässig in Docker, aber nicht mit dem Standard-Image allein. Erst das eigene Image mit PostgreSQL-Treiber und eine eingebundene superset_config.py machen aus dem Container einen Dienst mit dauerhafter Metadaten-Datenbank, Redis-Cache und funktionierenden Hintergrundaufgaben. Mit Port 8088 an 127.0.0.1, HTTPS am Proxy, Leserechten für Datenquellen und einem getesteten pg_dump haben Sie eine solide Grundlage für Dashboards im eigenen Unternehmen.

Weiterführende Anleitungen und Quellen