Skip to content

Aufgabe 09 - InfluxDB mit Grafana

Switch to Zen Mode

InfluxDB und Grafana sollen ausprobiert und damit etwas kennengelernt werden. Die Übung umfasst:

  • Testdaten mit Mockaroo erzeugen (CSV)
  • InfluxDB (OSS 2.x) per Docker Compose starten und initial konfigurieren
  • CSV-Daten in InfluxDB importieren (CLI)
  • Daten in Grafana als Dashboard visualisieren (Flux / InfluxDB 2.x)
  • Docker + Docker Compose installiert
  • Browserzugang zu https://mockaroo.com/
  • Optional: influx CLI lokal installiert oder Import über einen CLI-Container

Anmerkung: InfluxDB wird beim Start per Docker Compose automatisch vorkonfiguriert, statt manuell im Web-Setup.

Erstelle auf Mockaroo ein Schema mit z. B. 10.000 Zeilen und exportiere dieses als CSV.

Spalten (Beispiel “Smart Building Sensoren”)

  • _measurementFormula → Gib "sensors" ein (konstanter Wert für alle Zeilen)
  • timeDatetime (Format ISO 8601, z. B. 2026-01-20T12:34:56Z)
  • buildingCustom List (z. B. E101, E102, LAB1, LAB2)
  • deviceCustom List (z. B. device1, device2, device3, device4)
  • temperature_cNumber (z. B. 18–28, decimals 1)
  • humidity_rhNumber (z. B. 25–65, decimals 1)
  • co2_ppmNumber (z. B. 400–2000, decimals 0)
  • power_wNumber (z. B. 0–2500, decimals 0)

Hinweis (wichtig):

  • Mockaroo kann in der kostenlosen Version pro Export maximal 1.000 Zeilen exportieren.
  • _measurement ist Pflicht für InfluxDB - verwende den Typ Formula mit dem Wert "sensors"
  • time wird später als Timestamp verwendet.
  • building, device eignen sich als Tags (Filter/Gruppierung).
  • Messwerte (temperature_c, …) sind Fields.
  • Reihenfolge beachten: _measurement,time,building,device,temperature_c,humidity_rh,co2_ppm,power_w

Lege einen Projekt-Ordner an, z. B. influx-grafana-lab/ und darin diese Struktur:

influx-grafana-lab/
docker-compose.yml
grafana/
provisioning/
datasources/
datasource.yml
data/ (optional, falls CSV hier liegt)

Stelle dieses docker-compose.yml ins Projekt:

services:
influxdb:
image: influxdb:2
container_name: influxdb
ports:
- "8086:8086"
volumes:
- influxdb_data:/var/lib/influxdb2
- influxdb_config:/etc/influxdb2
environment:
- DOCKER_INFLUXDB_INIT_MODE=setup
- DOCKER_INFLUXDB_INIT_USERNAME=admin
- DOCKER_INFLUXDB_INIT_PASSWORD=adminadminadmin
- DOCKER_INFLUXDB_INIT_ORG=school
- DOCKER_INFLUXDB_INIT_BUCKET=sensors
- DOCKER_INFLUXDB_INIT_RETENTION=0 # keine Vorhaltezeit, alle Daten behalten
- DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=school-super-token
grafana:
image: grafana/grafana:latest
container_name: grafana
ports:
- "3000:3000" # Falls Port 3000 belegt ist, z.B.: "4000:3000"
depends_on:
- influxdb
volumes:
- grafana_data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning
volumes:
influxdb_data:
influxdb_config:
grafana_data:

Lege folgende Datei in deinem Projektordner an. Sie wird dann von Docker in den Grafana-Container hineingemountet.

(grafana/provisioning/datasources/datasource.yml)

apiVersion: 1
datasources:
- name: InfluxDB_v2
type: influxdb
access: proxy
url: http://influxdb:8086
jsonData:
version: Flux
organization: school
defaultBucket: sensors
secureJsonData:
token: school-super-token

Grafana erwartet für InfluxDB 2.x (Flux) u. a. Organization/Bucket/Token.

Im Projekt-Ordner influx-grafana-lab/:

  • Starte den Container Stack mit docker compose up -d
  • Prüfe mit docker compose ps, ob beide Container laufen.

Wenn beide Container laufen, dann sollte die UI im Browser erreichbar sein:

  • InfluxDB UI: http://localhost:8086
  • Grafana UI: http://localhost:3000 (bzw. die verwendete Portnummer) Verwende beim ersten Login: user/password = admin/admin und setze ein neues Passwort.

InfluxDB kann CSV-Files über die Browser-GUI oder über influx write importieren.

Da InfluxDB ein spezielles annotated CSV-Format erwartet, müssen Header-Optionen angegeben werden, die die Datentypen und Spaltennamen definieren.

Details zum CSV-Import-Format: https://docs.influxdata.com/influxdb/cloud/reference/syntax/annotated-csv/#annotated-csv-in-flux

5.1 Import über einen CLI-Container (ohne lokale Installation)

Abschnitt betitelt „5.1 Import über einen CLI-Container (ohne lokale Installation)“

Damit der Influx-Client nicht auf der lokalen Maschine installiert werden muss, kann man einfach einen Container für den Import erstellen und verwenden, der nach dem Import sofort wieder gelöscht wird (—rm).

Das benötigte CSV-File für den Import wird nicht in den Container kopiert sondern einfach nur gemountet. Das ist schneller und funktioniert auch für große Datenmengen.

Das CSV liegt z. B. in ./data/MOCK_DATA.csv.

PowerShell:

Terminal-Fenster
docker run --rm -it `
--network influx-grafana-lab_default `
-v "${PWD}/data:/data" `
influxdb:2 `
influx write `
--host http://influxdb:8086 `
--org school `
--bucket sensors `
--token school-super-token `
--format csv `
--header "#datatype measurement,dateTime:RFC3339,tag,tag,double,double,long,long" `
--header "_measurement,time,building,device,temperature_c,humidity_rh,co2_ppm,power_w" `
--skipHeader 1 `
--file /data/MOCK_DATA.csv

Für z.B. Bash/Linux ersetze ${PWD} durch $(pwd).

Erklärung der Header-Optionen:

  • #datatype definiert die Typen: measurement (Messungsname), dateTime:RFC3339 (Zeitstempel), tag (für Gruppierung), double/long (Zahlen)
  • Zweiter Header listet die exakten Spaltennamen aus der CSV auf
  • --skipHeader 1 überspringt die CSV-Header-Zeile beim Import

Ein Import mit lokal installiertem influx CLI funktioniert analog, nur ohne docker run .... Details siehe https://docs.influxdata.com/influxdb/v2/tools/influx-cli/?t=Linux

Überprüfe nach dem Import per CLI oder mit dem Data Explorer über die InfluxDB-UI, ob der Import erfolgreich war.

Per CLI:

Terminal-Fenster
docker exec influxdb influx query 'from(bucket:"sensors") |> range(start:-2y) |> count()' --token school-super-token

Per Web-UI (Data Explorer):

  • Bucket: sensors
  • Measurement: sensors
  • Field: z.B. temperature_c
  • building: z.B. E101
  • device: z.B. device1
  • Zeitraum: Past 1 year (da die Mock-Daten zufällige Zeitstempel haben)

Wenn du Daten von der influx query erhälst bzw. im Data Explorer als Verlauf über die Zeit siehst, dann war der Import OK.

Öffne Grafana: http://localhost:3000 bzw. über das festgelegte Port

  1. Connections → Data sources
  2. Datasource InfluxDB_v2 auswählen
  3. Ganz unten auf Test klicken.

Wenn „Data source is working“ → OK

Nun kannst du in Grafana ein neues Dashboard erstellen:

  • Dashboards → New → New dashboard
  • Add visualization

Wichtige Panel-Settings gleich einstellen:

Im Panel-Editor:

  • Data source: InfluxDB_v2

  • Time range: Oben rechts im Dashboard passend auf z.B. “Previous week” oder “Previous year” etc. setzen.

  • Panel-Typ: Visualization wählen (Time series / Stat / Table)

  • Query: passende Influx-Query einfügen und mit dem Query inspector überprüfen.

    Beispiel-Flux-Query (als Vorlage)

    from(bucket: "sensors")
    |> range(start: -1y)
    |> filter(fn: (r) => r._measurement == "sensors")
    |> filter(fn: (r) => r._field == "temperature_c")
    |> group(columns: ["building"])

Danach kannst du zum neuen Dashboard wechseln, wo die erstellten Panels angezeigt werden.

Erstelle folgende Panels:

  1. Time series Panel: temperature_c über Zeit
    • Gruppierung nach building
  2. Time series Panel: co2_ppm über Zeit
    • Filter: nur building = "E101"
  3. Stat Panel: aktueller Wert von humidity_rh für ein Gebäude (z. B. LAB1)
  4. Table Panel: letzte Messwerte (Top 20) mit Spalten time, building, device, temperature_c, co2_ppm

Abzugebende Artefakte

  • verwendetes docker-compose.yml
  • verwendetes grafana/provisioning/datasources/datasource.yml
  • CSV-Schema-Beschreibung inkl. Header bzw die ersten 5 Zeilen vom CSV.
  • Pro Panel
    • Screenshot vom Grafana-Dashboard
    • kurze Beschreibung der Panels
    • Flux-Query
    • weitere benötigte Einstellungen
  • Kurzes README.md:
    • alle verwendeten Docker Commands
    • verwendetes Import Command

InfluxDB kann auch als Puffer-Datenbank zur Visualisierung von Live-Daten verwendet werden.

Die Daten müssen dazu fortlaufend aus einer Datenquelle in die InfluxDB geschrieben werden und werden dann mit Grafana visualisiert. Veraltete Daten werden automatisch über die Retention Policy gelöscht.

Das funktioniert z.B.

  • mit einem Python-Skript
  • mit dem Telegraf-Agent der InfluxDB
  • oder flexibel und ohne Coding mit Node Red

Für dynamische Werte eignen sich Kurse von Cryptowährungen, die z.B. über die Binance API abgerufen werden können.

Erstelle in der InfluxDB einen weiteren Bucket crypto mit 30 Tagen Vorhaltezeit.

Terminal-Fenster
docker exec influxdb influx bucket create --name crypto --org school --token school-super-token --retention 30d

Erweitere den Docker Stack um ein Node Red Service:

nodered:
image: nodered/node-red:latest
container_name: nodered
ports:
- "1880:1880"
environment:
- INFLUX_ORG=school
- INFLUX_BUCKET=crypto
- INFLUX_TOKEN=school-super-token
- INFLUX_URL=http://influxdb:8086
volumes:
- ./nodered-data:/data
depends_on:
- influxdb
restart: unless-stopped

Und starte den Stack mit dem neuen Service:

Terminal-Fenster
docker compose up -d

Öffne Node-RED: [http://localhost:1880]

Importiere diesen fertigen Flow (Menü → Import, via Clipboard):

[
{
"id": "inject_crypto",
"type": "inject",
"name": "Alle 5 Sekunden",
"props": [],
"repeat": "5",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"topic": "",
"x": 140,
"y": 100,
"wires": [["http_binance"]]
},
{
"id": "http_binance",
"type": "http request",
"name": "Binance API",
"method": "GET",
"ret": "obj",
"url": "https://api.binance.com/api/v3/ticker/price?symbols=[\"BTCUSDT\",\"ETHUSDT\",\"BNBUSDT\",\"ADAUSDT\",\"SOLUSDT\"]",
"x": 340,
"y": 100,
"wires": [["format_influx"]]
},
{
"id": "format_influx",
"type": "function",
"name": "Format für InfluxDB",
"func": "const lines = [];\nconst timestamp = Date.now() * 1000000;\n\nfor (const coin of msg.payload) {\n const symbol = coin.symbol;\n const price = parseFloat(coin.price);\n lines.push(`crypto_price,source=binance,symbol=${symbol} price=${price} ${timestamp}`);\n}\n\nmsg.payload = lines.join(\"\\n\");\nmsg.headers = {\n 'Authorization': 'Token school-super-token',\n 'Content-Type': 'text/plain; charset=utf-8'\n};\nreturn msg;",
"outputs": 1,
"x": 560,
"y": 100,
"wires": [["http_influx"]]
},
{
"id": "http_influx",
"type": "http request",
"name": "Schreibe zu InfluxDB",
"method": "POST",
"ret": "txt",
"url": "http://influxdb:8086/api/v2/write?org=school&bucket=crypto&precision=ns",
"x": 800,
"y": 100,
"wires": [["debug_output"]]
},
{
"id": "debug_output",
"type": "debug",
"name": "Status",
"active": true,
"console": false,
"complete": "payload",
"x": 1020,
"y": 100,
"wires": []
}
]

Rechts oben auf Deploy klicken und die Daten werden alle 5sec in die InfluxDB geschrieben.

Erstelle Dashboard mit folgenden Panels:

  • Panel 1: BTC Preis (Time Series)

    from(bucket: "crypto")
    |> range(start: -1h)
    |> filter(fn: (r) => r._measurement == "crypto_price")
    |> filter(fn: (r) => r._field == "price")
    |> filter(fn: (r) => r.symbol == "BTCUSDT")
  • Panel 2: Alle Coins (Time Series)

    from(bucket: "crypto")
    |> range(start: -1h)
    |> filter(fn: (r) => r._measurement == "crypto_price")
    |> filter(fn: (r) => r._field == "price")
  • Panel 3: Aktueller BTC Preis (Stat)

    from(bucket: "crypto")
    |> range(start: -5m)
    |> filter(fn: (r) => r._measurement == "crypto_price")
    |> filter(fn: (r) => r._field == "price")
    |> filter(fn: (r) => r.symbol == "BTCUSDT")
    |> last()
  • Panel 4: Preis-Tabelle (Table)

    from(bucket: "crypto")
    |> range(start: -1m)
    |> filter(fn: (r) => r._measurement == "crypto_price")
    |> filter(fn: (r) => r._field == "price")
    |> last()
    |> group()

Abzugebende Artefakte

  • erweitertes docker-compose.yml
  • Pro Panel
    • Screenshot vom Grafana-Dashboard
    • kurze Beschreibung der Panels
    • Flux-Query
    • weitere benötigte Einstellungen
  • README.md ergänzen:
    • alle verwendeten Docker Commands