Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Monitoring 21.09.2026 · 12 min Lesezeit

OpenObserve mit Docker Compose betreiben: Logs, Metriken und Traces auf einem Server

OpenObserve sammelt Logs, Metriken und Traces in einem Container. Die Anleitung zeigt den getesteten Betrieb mit Docker Compose, erste Log-Einträge per HTTP, SQL-Abfragen, Sicherung mit Wiederherstellung, Updates und typische Fehler.

Geprüft am 16.10.2026 · für OpenObserve 1.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

Illustration zur Anleitung: OpenObserve mit Docker betreiben, mit Karten für Logs, Metriken und Traces sowie einem abstrakten Dashboard

Logdateien liegen oft verstreut auf einzelnen Hosts, Metriken und Traces in weiteren Systemen. OpenObserve fasst Logs, Metriken und Traces in einer Anwendung zusammen, die als einzelner Container auf einem kleinen Server läuft. Die Anleitung zeigt den Betrieb mit Docker Compose vom ersten Log-Eintrag bis zu Sicherung und Update. Alle Befehle wurden mit Version v1.1.0 getestet.

Wofür sich OpenObserve eignet und wo die Grenzen liegen

OpenObserve ist eine quelloffene Observability-Plattform für Logs, Metriken, Traces und Frontend-Monitoring. Sie ist in Rust geschrieben, speichert Daten im Parquet-Format, unterstützt OpenTelemetry und lässt sich per SQL und PromQL abfragen. Der Betrieb als einzelnes Programm ohne zusätzliche Datenbank ist vorgesehen. Das Repository openobserve/openobserve steht unter AGPL-3.0; aktuelle stabile Version im Oktober 2026 ist v1.1.0 (14.10.2026).

Die Grenzen: Eine Einzelinstanz ist nicht hochverfügbar; fällt der Host aus, fehlt die Auswertung gerade im Störungsfall. Hochverfügbarkeit sieht das Projekt nur mit Kubernetes, Helm, Objektspeicher und PostgreSQL- oder MySQL-Metadatenbank vor. OpenObserve sammelt passiv und ersetzt keine aktive Überwachung von Ports, Diensten oder Zertifikaten.

Voraussetzungen und Ressourcenbedarf

  • Linux-Host mit Docker und dem Compose-Plugin (docker compose, nicht das alte docker-compose).
  • Für wenige Hosts: 2 CPU-Kerne und 2 GB RAM als Startpunkt (Erfahrungswert, keine offizielle Vorgabe). Im Test lief eine Einzelinstanz auch auf 1 CPU und 3 GB RAM. Bei größerem Datenvolumen wird zuerst der Arbeitsspeicher knapp.
  • Plattenplatz je nach Datenvolumen. Das Image ist rund 150 MB groß.
  • Getestet auf x86-64. Das Projekt liefert laut Dokumentation auch Binärdateien für Linux, macOS und Windows; ARM-Systeme wurden hier nicht geprüft.
# Docker-Version anzeigen
docker --version
# Compose-Plugin prüfen, muss eine Version ausgeben
docker compose version

Die Aufbewahrungsdauer steuert ZO_COMPACT_DATA_RETENTION_DAYS. Der Standardwert ist 3650 Tage (zehn Jahre), der Mindestwert 3. Ohne Anpassung löscht OpenObserve praktisch nichts; setzen Sie den Wert passend zu Ihren Anforderungen.

Verifizieren: docker compose version gibt eine Version 2.x aus.

Die compose.yaml im Detail

Die folgende Datei wurde so getestet:

services:
  openobserve:
    # Feste Version statt latest, damit ein Neustart nicht ungeplant aktualisiert
    image: public.ecr.aws/zinclabs/openobserve:v1.1.0
    container_name: openobserve
    # Container startet nach Reboot oder Absturz automatisch neu
    restart: unless-stopped
    environment:
      # Zugangsdaten des Administrators, aus der .env-Datei gelesen
      ZO_ROOT_USER_EMAIL: ${ZO_ROOT_USER_EMAIL}
      ZO_ROOT_USER_PASSWORD: ${ZO_ROOT_USER_PASSWORD}
      # Ablageort der Daten im Container, passend zum Volume unten
      ZO_DATA_DIR: /data
      # Anonyme Telemetrie an das Projekt abschalten
      ZO_TELEMETRY: "false"
    volumes:
      - openobserve_data:/data
    ports:
      # Nur auf localhost binden, Zugriff von außen über einen Reverse Proxy
      - "127.0.0.1:5080:5080"
volumes:
  openobserve_data:
  • image: offizielles Image mit festem Tag. Mit latest würde ein späteres docker compose pull unbemerkt eine andere Version laden.
  • container_name: erleichtert Befehle wie docker logs openobserve; bei mehreren Instanzen weglassen.
  • ZO_ROOT_USER_EMAIL / ZO_ROOT_USER_PASSWORD: legen das Administratorkonto beim ersten Start an. Die E-Mail-Adresse ist der Anmeldename.
  • ZO_DATA_DIR: passt den Datenpfad an das Volume an. Darunter liegen Metadatenbank, Write-Ahead-Log und Streams.
  • ZO_TELEMETRY: steht standardmäßig auf true. Der Wert "false" steht in Anführungszeichen, weil die Anwendung eine Zeichenkette erwartet.
  • ports: Ohne 127.0.0.1 wäre die Oberfläche unverschlüsselt aus dem ganzen Netz erreichbar. 5080 ist der Standardwert von ZO_HTTP_PORT.
  • Kein healthcheck: Das Image ist minimal und enthält weder /bin/sh noch wget oder curl. Ein Healthcheck mit CMD-SHELL oder wget schlägt dauerhaft fehl (im Test: „stat /bin/sh: no such file or directory“), der Container bleibt „health: starting“ bzw. „unhealthy“. Überwachen Sie /healthz stattdessen von außen, etwa mit Uptime Kuma.

Verifizieren: docker compose config --quiet && echo OK gibt OK aus.

Eine .env-Datei für die Zugangsdaten

Das Administratorpasswort gehört nicht in die compose.yaml. Compose liest Variablen automatisch aus der Datei .env im selben Verzeichnis.

# .env - Platzhalter, vor dem Einsatz ersetzen
ZO_ROOT_USER_EMAIL=admin@beispiel.local
ZO_ROOT_USER_PASSWORD=IHR_LANGES_PASSWORT

OpenObserve prüft das Root-Passwort bei jedem Start: Es muss 8 bis 128 Zeichen lang sein und mindestens einen Klein- und einen Großbuchstaben, eine Ziffer und ein Sonderzeichen enthalten. Ein reines openssl rand -base64 24 erfüllt das nicht zuverlässig, weil die Ausgabe nicht immer eine Ziffer oder ein Sonderzeichen enthält. Hängen Sie deshalb einen festen Rest an, etwa mit printf '%s-Aa1\n' "$(openssl rand -base64 24)". Wer das Verzeichnis mit Git verwaltet, trägt .env in die .gitignore ein.

# Nur der Besitzer darf lesen und schreiben
chmod 600 .env
# Ergebnis kontrollieren, erwartet wird -rw-------
ls -l .env

Verifizieren: ls -l .env zeigt -rw-------, und docker compose config | grep ZO_ROOT_USER_EMAIL zeigt Ihre Adresse.

Installation und erster Start

Legen Sie ein eigenes Verzeichnis an und speichern Sie dort compose.yaml und .env. Der Verzeichnisname bestimmt den Compose-Projektnamen und damit den Volume-Namen (openobserve_openobserve_data).

sudo mkdir -p /opt/openobserve
sudo chown "$USER": /opt/openobserve
cd /opt/openobserve
# Image laden und Container im Hintergrund starten
docker compose up -d
# Status anzeigen
docker compose ps
# Startmeldungen ansehen
docker compose logs --tail 50 openobserve

Verifizieren: docker compose ps zeigt den Container mit Up. Beendet er sich sofort, nennt die Logausgabe den Grund (siehe Typische Fehler).

Funktionsprüfung und erster Log-Eintrag

Der Gesundheitsendpunkt ist ohne Anmeldung erreichbar:

curl -s http://127.0.0.1:5080/healthz
# Erwartet: {"status":"ok"}
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:5080/web/
# Erwartet: 200

Auf einem entfernten Server erreichen Sie die Oberfläche vor der Einrichtung eines Reverse Proxys über einen SSH-Tunnel unter http://127.0.0.1:5080/web/:

ssh -L 5080:127.0.0.1:5080 benutzer@servername

OpenObserve nimmt Logs per POST /api/{organisation}/{stream}/_json als JSON-Array an. Die Standardorganisation heißt default, der Stream entsteht beim ersten Schreiben. Die Anmeldung erfolgt per Basic-Auth mit den Root-Zugangsdaten.

# Zugangsdaten aus der .env in die Shell laden
set -a
. ./.env
set +a
# Einen Testdatensatz in den Stream testlogs schreiben
curl -s -u "$ZO_ROOT_USER_EMAIL:$ZO_ROOT_USER_PASSWORD" \
  -H "Content-Type: application/json" \
  -d '[{"level":"info","service":"testdienst","message":"Erster Eintrag"}]' \
  http://127.0.0.1:5080/api/default/testlogs/_json

Antwort im Test:

{"code":200,"status":[{"name":"testlogs","successful":1,"failed":0}]}

Entscheidend sind successful und failed: code 200 bedeutet nur, dass die Anfrage angenommen wurde. Bei Sammelanfragen kann failed größer als null sein, obwohl code 200 lautet.

# Streams der Organisation default auflisten
curl -s -u "$ZO_ROOT_USER_EMAIL:$ZO_ROOT_USER_PASSWORD" \
  http://127.0.0.1:5080/api/default/streams

Abfragen laufen per POST /api/default/_search mit einem Zeitfenster in Mikrosekunden:

# Aktueller Zeitpunkt und vor einer Stunde, in Mikrosekunden
NOW=$(date +%s000000)
AGO=$(( $(date -d '1 hour ago' +%s)000000 ))
# Die letzten fünf Einträge aus dem Stream testlogs abfragen
curl -s -u "$ZO_ROOT_USER_EMAIL:$ZO_ROOT_USER_PASSWORD" \
  -H "Content-Type: application/json" \
  -d "{\"query\":{\"sql\":\"SELECT * FROM testlogs\",\"start_time\":$AGO,\"end_time\":$NOW,\"from\":0,\"size\":5}}" \
  http://127.0.0.1:5080/api/default/_search

Verifizieren: Die Antwort enthält "total":1 und den Eintrag mit dem Feld _timestamp (ebenfalls in Mikrosekunden; für Unix-Sekunden durch eine Million teilen). Die Liste der Streams enthält testlogs.

Persistente Daten, Rechte und was beim Neustart passiert

Alle Daten (Streams, Metadatenbank, Benutzerkonten) liegen im Volume, im Container unter /data. Compose stellt dem Volume den Projektnamen voran; bei /opt/openobserve heißt es openobserve_openobserve_data. docker compose down entfernt den Container, das Volume bleibt erhalten.

docker volume ls | grep openobserve
docker volume inspect openobserve_openobserve_data

Beim benannten Volume verwaltet Docker die Rechte. Wer stattdessen ein Hostverzeichnis einhängt, muss Schreibrechte für den Benutzer im Container sicherstellen, sonst beendet sich der Container mit einem Schreibfehler. Nach einem Host-Neustart startet der Container dank restart: unless-stopped wieder, sofern der Docker-Dienst aktiviert ist (systemctl is-enabled docker).

Verifizieren: Nach docker compose down und docker compose up -d liefert die Abfrage aus dem vorigen Abschnitt weiterhin den Testeintrag.

Sichere Netzwerkfreigabe und Reverse Proxy mit TLS

Ohne 127.0.0.1 vor dem Port bindet Docker an alle Schnittstellen und trägt seine Regeln an der Host-Firewall vorbei ein. Die Anmeldemaske mit Zugriff auf alle Logs wäre dann unverschlüsselt im Netz erreichbar.

Für den Zugriff von außen gehört ein Reverse Proxy mit TLS davor. Dieser Abschnitt wurde nicht getestet:

  1. Reverse Proxy auf Port 443 mit automatischem Zertifikat betreiben.
  2. Einen eigenen DNS-Namen für den Dienst vergeben.
  3. An http://127.0.0.1:5080 weiterleiten und die Kopfzeilen X-Forwarded-For und X-Forwarded-Proto setzen.
  4. Zugang auf Firmennetz oder VPN beschränken.
  5. Prüfen, dass Port 5080 von außen nicht erreichbar ist.

Läuft der Proxy selbst als Container, ist 127.0.0.1 dort nicht der Host. Hängen Sie dann beide Dienste in ein gemeinsames Docker-Netzwerk, sprechen Sie OpenObserve über den Dienstnamen an und entfernen Sie die Portfreigabe.

Verifizieren: Von einem anderen Rechner schlägt curl http://SERVER-IP:5080/healthz fehl, über die Domain antwortet https://…/healthz mit {"status":"ok"}.

Backup und Wiederherstellung

Zur Sicherung gehören compose.yaml, .env (verschlüsselt ablegen, enthält das Passwort) und das Volume. Achten Sie auf den vollständigen Volume-Namen: -v openobserve_data:/data würde ein neues, leeres Volume anlegen und ein leeres Archiv erzeugen. Der folgende Ablauf wurde im Test vollständig durchgespielt, einschließlich Wiederherstellung:

cd /opt/openobserve
# Dienst vor der Sicherung anhalten
docker compose stop
# Volume in ein tar-Archiv im aktuellen Verzeichnis sichern
docker run --rm \
  -v openobserve_openobserve_data:/data:ro \
  -v "$PWD":/backup \
  alpine tar czf /backup/openobserve-data.tar.gz -C /data .
# Dienst wieder starten
docker compose start

Die Wiederherstellung läuft umgekehrt in ein leeres Volume:

docker compose down
docker volume rm openobserve_openobserve_data
docker volume create openobserve_openobserve_data
docker run --rm \
  -v openobserve_openobserve_data:/data \
  -v "$PWD":/backup \
  alpine tar xzf /backup/openobserve-data.tar.gz -C /data
docker compose up -d

Ein von Hand angelegtes Volume entfernt docker compose down -v später allerdings nicht, dafür ist docker volume rm nötig (im Test bestätigt). Bei Anbindung an einen Objektspeicher liegen die Daten nicht lokal; diese Betriebsart wurde nicht getestet.

Verifizieren: tar tzf openobserve-data.tar.gz | head listet Dateien, das Archiv ist größer als wenige KB. Nach der Wiederherstellung liefert SELECT count(*) AS n FROM testlogs denselben Wert wie vorher.

Updates und die Grenzen eines Rollbacks

Ablauf: Sicherung anlegen, Release Notes lesen, Tag in der compose.yaml ändern, Image laden, Container ersetzen, Logs prüfen.

# Aktuell laufende Version anzeigen
docker compose images
# Nach dem Anpassen des Tags: neues Image laden und Container ersetzen
docker compose pull
docker compose up -d
# Startmeldungen auf Migrationshinweise oder Fehler durchsehen
docker compose logs --tail 100 openobserve

Ein Rollback nur über den alten Tag ist nicht garantiert: Eine ältere Version kann Daten, die eine neuere bereits migriert hat, oft nicht lesen. Belastbar ist nur der alte Tag zusammen mit der Sicherung von vor dem Update.

Im Test am 16.10.2026 lief das Update von v1.0.4 auf v1.1.0 mit genau diesen Befehlen. Beim ersten Start meldete das Log DB_SCHEMA_VERSION mismatch : expected 97, found 77; running db upgrade und spielte die Migrationen selbst ein. Danach war ein vorher geschriebener Eintrag weiter abfragbar, neue Einträge kamen an, die Oberfläche antwortete mit HTTP 200 und ein falsches Passwort mit 401. Auch eine Sicherung des migrierten Volumes ließ sich zurückspielen und lieferte beide Einträge wieder. Laut Release Notes bringt 1.1.0 vor allem PromQL-Erweiterungen, einen neu gebauten Service-Graphen und öffentliche Statusseiten, neue Pflichtvariablen für den Einzelbetrieb nennt sie nicht. Prüfen Sie vor dem Update das Root-Passwort in der .env gegen die Passwortregel aus dem Abschnitt zur .env-Datei: Ein zu schwaches Passwort lässt auch 1.1.0 nicht starten.

Verifizieren: docker compose images zeigt den neuen Tag, /healthz meldet ok, und eine Beispielabfrage liefert Daten.

Typische Fehler mit Diagnose und Lösung

Suche scheitert mit invalid time range

Im Test aufgetreten: _search mit "start_time":0 und einem beliebig großen end_time wird nicht als „gesamter Zeitraum“ verstanden, sondern abgelehnt:

{"code":400,"message":"Error# [file_list] invalid time range"}

Die Ursache ist das Zeitfenster, nicht die SQL-Anweisung. Erzeugen Sie die Grenzen in Mikrosekunden wie oben gezeigt. Ein Fenster in Sekunden liefert keine Treffer.

Keine Shell im Container verfügbar

Im Test aufgetreten: docker compose exec openobserve /bin/sh scheitert mit

exec failed: unable to start container process: exec: "/bin/sh": stat /bin/sh: no such file or directory

Das Image enthält bewusst keine Shell und keine Werkzeuge. Diagnostizieren Sie von außen: docker compose logs, docker inspect, HTTP-Endpunkte, Dateien per docker cp oder das Volume in einem Hilfscontainer wie beim Backup. Aus demselben Grund funktioniert kein Docker-Healthcheck innerhalb des Containers.

Port bereits belegt

Ist Port 5080 belegt, verweigert Compose den Start mit „address already in use“. Prüfen Sie mit ss -tlnp | grep 5080 und ändern Sie nur die linke Seite der Portangabe, etwa "127.0.0.1:5081:5080".

Anmeldung schlägt fehl

Zwei Ursachen sind wahrscheinlich: Sonderzeichen im Passwort wurden von der Shell ausgewertet; prüfen Sie mit docker compose config, welche Werte Compose einsetzt. Oder das Passwort wurde nachträglich in der .env geändert: Die Root-Zugangsdaten wirken laut Dokumentation nur beim ersten Start. Ändern Sie das Passwort in der Benutzerverwaltung der Oberfläche.

Container startet nicht oder beendet sich sofort

Häufige Ursachen sind fehlende Schreibrechte bei eingehängtem Hostverzeichnis, YAML-Einrückungsfehler und ein zu schwaches Root-Passwort. Im Test mit einem Passwort nur aus Kleinbuchstaben und Ziffern startete der Container in einer Neustartschleife, /healthz blieb unerreichbar, und das Log zeigte:

ZO_ROOT_USER_PASSWORD is too weak: Password must be 8-128 characters and contain at least one lowercase letter, one uppercase letter, one digit, and one special character.

Setzen Sie dann ein Passwort nach der Regel aus dem Abschnitt zur .env-Datei und starten Sie mit docker compose up -d neu.

docker compose logs openobserve
# Zeigt die Konfiguration nach Einsetzen der Variablen, deckt leere Werte auf
docker compose config

Saubere Deinstallation mit Warnung vor Datenverlust

Dieser Befehl entfernt Container und Netzwerk, die Daten bleiben erhalten:

docker compose down

Achtung: Der folgende Befehl löscht zusätzlich das Volume mit allen Logs, Metadaten und Benutzerkonten, ohne Rückfrage. Ohne Sicherung ist das nicht umkehrbar. Prüfen Sie vorher, dass Sie im richtigen Verzeichnis sind:

docker compose down -v
# Image entfernen
docker image rm public.ecr.aws/zinclabs/openobserve:v1.1.0
# Prüfen, ob das Volume entfernt ist (ein von Hand angelegtes bleibt)
docker volume ls | grep openobserve

Löschen Sie danach das Verzeichnis /opt/openobserve einschließlich .env.

Verifizieren: docker ps -a und docker volume ls zeigen keinen Eintrag mit openobserve mehr.

Passende Anleitungen auf S-EDV

Quellen

OpenObserveDocker ComposeObservabilityLogsMonitoringSelfhostingTraces