IoT-Tutorials

TIG-Stack mit Docker Compose für MQTT-Daten

Ein vollständiges docker-compose-Setup für Telegraf, InfluxDB 2 und Grafana, das einen MQTT-Broker abonniert, Sensordaten speichert und mit provisionierter Datenquelle und Dashboard startet, dazu die Fallstricke, an denen erste Starts scheitern.

Diagramm eines TIG-Stacks mit Docker Compose, in dem Telegraf MQTT-Topics liest, InfluxDB Metriken speichert und Grafana Dashboards zeigt
Probieren Sie es auf Ihrem eigenen MQTT-Broker ausHolen Sie sich im Free-Tarif einen privaten, verwalteten MQTT-Broker und starten Sie mit fertigen Codebeispielen.
Kostenlos testen Codebeispiele Keine Kreditkarte erforderlich

Ein TIG-Stack mit Docker Compose liefert Ihnen eine vollständige MQTT-Datenpipeline auf einem einzigen Rechner: Telegraf abonniert Ihren Broker, InfluxDB speichert die Messwerte und Grafana stellt sie dar. In diesem Leitfaden erstellen Sie jede benötigte Datei, starten den Stack mit einem Befehl und öffnen in Grafana ein Dashboard, das bereits provisioniert ist und Live-Daten zeigt.

Was Sie bauen

Der Stack besteht aus drei Containern und einer externen Abhängigkeit, dem MQTT-Broker:

devices / simulator --> MQTT broker (broker.connectmq.com)
                              |
                         Telegraf (mqtt_consumer)
                              |
                         InfluxDB 2 (bucket "sensors")
                              |
                         Grafana (provisioned data source + dashboard)

Der Broker bleibt bewusst außerhalb von Compose. Broker sind langlebige Infrastruktur, die sich viele Consumer teilen; der TIG-Stack ist einer dieser Consumer. Telegraf verbindet sich als gewöhnlicher MQTT-Client mit dem Broker, was für den öffentlichen MQTT-Broker und für einen privaten Broker gleich funktioniert.

Warum Docker Compose für den TIG-Stack?

Jedes der drei Werkzeuge lässt sich nativ installieren, doch das bedeutet drei Paketquellen, drei Service-Definitionen und über das System verstreute Konfigurationsdateien. Compose bündelt die gesamte Pipeline in einem Ordner, den Sie versionieren, auf einen anderen Rechner kopieren oder spurlos abbauen können. Außerdem werden Versionen explizit festgelegt, sodass ein Betriebssystem-Update InfluxDB oder Grafana nie hinter Ihrem Rücken aktualisiert.

Der Kompromiss: Compose ist ein Werkzeug für einen einzelnen Host. Es passt gut zu einem Entwicklungs-Laptop, einem Labor, einem kleinen Standort-Gateway oder einem On-Premises-Server, der Daten aus einem Werk sammelt. Hochverfügbarkeit bietet es nicht; fällt der Host aus, fällt auch der Stack aus. Für viele Monitoring-Anwendungsfälle ist das akzeptabel, denn die Geräte veröffentlichen weiter an den Broker und Telegraf macht weiter, sobald es zurück ist; und wenn Sie Telegraf auf QoS 1 mit persistent_session = true umstellen, kann der Broker dessen Nachrichten während eines kurzen Ausfalls vorhalten.

Projektstruktur

Legen Sie diese Verzeichnisstruktur an:

tig-mqtt/
  .env
  docker-compose.yml
  telegraf/
    telegraf.conf
  grafana/
    provisioning/
      datasources/
        influxdb.yml
      dashboards/
        dashboards.yml
    dashboards/
      mqtt-sensors.json

Insgesamt sechs Dateien. Jede wird unten vollständig gezeigt.

Schritt 1: Umgebungsvariablen

Geheimnisse und Namen liegen in .env, das Docker Compose automatisch einliest. Halten Sie diese Datei aus der Versionsverwaltung heraus.

# .env
INFLUX_USERNAME=admin
INFLUX_PASSWORD=change-me-please
INFLUX_ORG=iot
INFLUX_BUCKET=sensors
INFLUX_TOKEN=replace-with-a-long-random-token
GRAFANA_PASSWORD=change-me-too

MQTT_SERVER=tcp://broker.connectmq.com:1883
MQTT_TOPIC_PREFIX=connectmq/demo/a1b2c3
MQTT_CLIENT_ID=telegraf-a1b2c3
MQTT_USERNAME=
MQTT_PASSWORD=

Erzeugen Sie ein echtes Token mit openssl rand -hex 32. Ersetzen Sie a1b2c3 durch Ihre eigene zufällige Zeichenfolge, damit Ihre Topics auf dem öffentlichen MQTT-Broker getrennt bleiben. Der öffentliche MQTT-Broker ist nur für Tests und Prototypen gedacht, nicht für Produktivdaten.

Schritt 2: Die Docker-Compose-Datei für den TIG-Stack

# docker-compose.yml
services:
  influxdb:
    image: influxdb:2.7
    restart: unless-stopped
    ports:
      - "8086:8086"
    environment:
      DOCKER_INFLUXDB_INIT_MODE: setup
      DOCKER_INFLUXDB_INIT_USERNAME: ${INFLUX_USERNAME}
      DOCKER_INFLUXDB_INIT_PASSWORD: ${INFLUX_PASSWORD}
      DOCKER_INFLUXDB_INIT_ORG: ${INFLUX_ORG}
      DOCKER_INFLUXDB_INIT_BUCKET: ${INFLUX_BUCKET}
      DOCKER_INFLUXDB_INIT_RETENTION: 30d
      DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: ${INFLUX_TOKEN}
    volumes:
      - influxdb-data:/var/lib/influxdb2
      - influxdb-config:/etc/influxdb2
    healthcheck:
      test: ["CMD", "influx", "ping"]
      interval: 10s
      timeout: 5s
      retries: 12

  telegraf:
    image: telegraf:1.32
    restart: unless-stopped
    depends_on:
      influxdb:
        condition: service_healthy
    environment:
      INFLUX_TOKEN: ${INFLUX_TOKEN}
      INFLUX_ORG: ${INFLUX_ORG}
      INFLUX_BUCKET: ${INFLUX_BUCKET}
      MQTT_SERVER: ${MQTT_SERVER}
      MQTT_TOPIC_PREFIX: ${MQTT_TOPIC_PREFIX}
      MQTT_CLIENT_ID: ${MQTT_CLIENT_ID}
      MQTT_USERNAME: ${MQTT_USERNAME}
      MQTT_PASSWORD: ${MQTT_PASSWORD}
    volumes:
      - ./telegraf/telegraf.conf:/etc/telegraf/telegraf.conf:ro

  grafana:
    image: grafana/grafana:11.3.0
    restart: unless-stopped
    depends_on:
      - influxdb
    ports:
      - "3000:3000"
    environment:
      GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD}
      INFLUX_TOKEN: ${INFLUX_TOKEN}
      INFLUX_ORG: ${INFLUX_ORG}
      INFLUX_BUCKET: ${INFLUX_BUCKET}
    volumes:
      - grafana-data:/var/lib/grafana
      - ./grafana/provisioning:/etc/grafana/provisioning:ro
      - ./grafana/dashboards:/var/lib/grafana/dashboards:ro

volumes:
  influxdb-data:
  influxdb-config:
  grafana-data:

Der Healthcheck ist wichtig. Ohne ihn kann Telegraf starten, bevor InfluxDB die Ersteinrichtung abgeschlossen hat, bei den ersten Schreibvorgängen scheitern und die Logs mit Fehlern füllen. condition: service_healthy lässt Compose warten, bis influx ping erfolgreich ist.

Schritt 3: Telegraf-Konfiguration

Telegraf ersetzt ${VAR}-Verweise aus seiner Umgebung, die Konfigurationsdatei enthält also keine Geheimnisse.

# telegraf/telegraf.conf
[agent]
  interval = "10s"
  flush_interval = "10s"
  omit_hostname = true

[[inputs.mqtt_consumer]]
  servers = ["${MQTT_SERVER}"]
  topics = ["${MQTT_TOPIC_PREFIX}/+/+/telemetry"]
  qos = 0
  client_id = "${MQTT_CLIENT_ID}"
  username = "${MQTT_USERNAME}"
  password = "${MQTT_PASSWORD}"

  name_override = "sensor"
  topic_tag = ""
  data_format = "json"
  tag_keys = ["device"]
  json_time_key = "ts"
  json_time_format = "unix_ms"

  [[inputs.mqtt_consumer.topic_parsing]]
    topic = "${MQTT_TOPIC_PREFIX}/+/+/telemetry"
    tags = "_/_/_/line/_/_"

[[outputs.influxdb_v2]]
  urls = ["http://influxdb:8086"]
  token = "${INFLUX_TOKEN}"
  organization = "${INFLUX_ORG}"
  bucket = "${INFLUX_BUCKET}"

Beachten Sie die URL http://influxdb:8086: Innerhalb des Compose-Netzwerks erreichen sich Container über den Service-Namen, nicht über localhost. Das tags-Muster setzt ein dreistufiges Präfix wie connectmq/demo/a1b2c3 voraus; hat Ihr Präfix eine andere Tiefe, passen Sie die Anzahl der führenden Unterstriche an. Eine zeilenweise Erklärung dieser Optionen finden Sie im Leitfaden zum Telegraf MQTT Consumer.

Schritt 4: Die Grafana-Datenquelle provisionieren

Die Provisionierung legt die InfluxDB-Datenquelle beim Start an, sodass sich niemand durch die Oberfläche klicken muss. Grafana expandiert Umgebungsvariablen auch in Provisionierungsdateien.

# grafana/provisioning/datasources/influxdb.yml
apiVersion: 1
datasources:
  - name: InfluxDB
    uid: influxdb
    type: influxdb
    access: proxy
    url: http://influxdb:8086
    isDefault: true
    jsonData:
      version: Flux
      organization: ${INFLUX_ORG}
      defaultBucket: ${INFLUX_BUCKET}
    secureJsonData:
      token: ${INFLUX_TOKEN}

Die feste uid erlaubt es dem Dashboard, zuverlässig auf diese Datenquelle zu verweisen.

Schritt 5: Ein fertiges Dashboard provisionieren

Teilen Sie Grafana zuerst mit, wo die Dashboards liegen:

# grafana/provisioning/dashboards/dashboards.yml
apiVersion: 1
providers:
  - name: mqtt
    folder: MQTT
    type: file
    options:
      path: /var/lib/grafana/dashboards

Fügen Sie dann das Dashboard selbst hinzu. Es enthält eine Temperatur-Zeitreihe pro Gerät und ein Stat-Panel mit der Anzahl der meldenden Geräte.

{
  "uid": "mqtt-sensors",
  "title": "MQTT Sensors",
  "schemaVersion": 39,
  "refresh": "10s",
  "time": { "from": "now-1h", "to": "now" },
  "panels": [
    {
      "id": 1,
      "type": "timeseries",
      "title": "Temperature by device",
      "gridPos": { "x": 0, "y": 0, "w": 18, "h": 10 },
      "datasource": { "type": "influxdb", "uid": "influxdb" },
      "fieldConfig": { "defaults": { "unit": "celsius" }, "overrides": [] },
      "targets": [
        {
          "refId": "A",
          "query": "from(bucket: \"sensors\")\n  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n  |> filter(fn: (r) => r._measurement == \"sensor\" and r._field == \"temperature\")\n  |> group(columns: [\"device\"])\n  |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)"
        }
      ]
    },
    {
      "id": 2,
      "type": "stat",
      "title": "Reporting devices (last 5 min)",
      "gridPos": { "x": 18, "y": 0, "w": 6, "h": 10 },
      "datasource": { "type": "influxdb", "uid": "influxdb" },
      "targets": [
        {
          "refId": "A",
          "query": "from(bucket: \"sensors\")\n  |> range(start: -5m)\n  |> filter(fn: (r) => r._measurement == \"sensor\" and r._field == \"temperature\")\n  |> group()\n  |> distinct(column: \"device\")\n  |> count()"
        }
      ]
    }
  ]
}

Wenn Sie den Bucket-Namen in .env geändert haben, ändern Sie "sensors" auch in den beiden Abfragen. Sie können dieses JSON auch in jeder bestehenden Grafana-Instanz über Dashboards, dann New, dann Import einspielen.

Schritt 6: Den Stack starten und Daten senden

cd tig-mqtt
docker compose up -d
docker compose ps
docker compose logs -f telegraf

Veröffentlichen Sie nun Daten. Die schnellste kontinuierliche Quelle ist unser Python-MQTT-Gerätesimulator; starten Sie ihn mit --prefix connectmq/demo/a1b2c3, damit er zu MQTT_TOPIC_PREFIX passt. Eine einzelne Testnachricht funktioniert ebenfalls:

mosquitto_pub -h broker.connectmq.com -p 1883 -i pub-a1b2c3 \
  -t connectmq/demo/a1b2c3/line1/sensor-0001/telemetry \
  -m "{\"device\":\"sensor-0001\",\"ts\":$(date +%s%3N),\"temperature\":22.4,\"humidity\":41.0}"

Öffnen Sie http://localhost:3000, melden Sie sich als admin mit GRAFANA_PASSWORD an und öffnen Sie das Dashboard MQTT Sensors im Ordner MQTT.

Jede Schicht der Reihe nach prüfen

Wenn das Dashboard leer bleibt, widerstehen Sie dem Drang, mehrere Dinge gleichzeitig zu ändern. Gehen Sie die Pipeline hinunter und bestätigen Sie jede Schicht, bevor Sie zur nächsten wechseln:

  1. Broker. Führen Sie mosquitto_sub -h broker.connectmq.com -p 1883 -i check-a1b2c3 -t "connectmq/demo/a1b2c3/#" -v aus. Erscheint nichts, liegt das Problem beim Publisher, nicht beim Stack.
  2. Telegraf-Verbindung. docker compose logs telegraf sollte zeigen, dass sich das Plugin fehlerfrei verbindet. Authentifizierungsfehler und Topic-Parsing-Fehler erscheinen hier.
  3. Telegraf-Parsing. Fügen Sie vorübergehend einen [[outputs.file]]-Block mit files = ["stdout"] hinzu und starten Sie Telegraf neu. Geparste Metriken erscheinen dann als Line Protocol in den Logs, was beweist, dass JSON- und Topic-Mapping stimmen.
  4. InfluxDB. Führen Sie docker compose exec influxdb influx query 'from(bucket: "sensors") |> range(start: -5m) |> limit(n: 3)' aus. Die CLI im Container ist durch das Init-Setup bereits konfiguriert.
  5. Grafana. Öffnen Sie die Seite der Datenquelle und klicken Sie auf Save and test; prüfen Sie dann, ob der Zeitraum des Dashboards die Zeit abdeckt, in der Daten geschrieben wurden.

In der Praxis werden die meisten Probleme in Schritt 1 oder Schritt 3 gefunden: ein Topic-Präfix, das sich um ein Zeichen unterscheidet, oder eine Payload, die nicht das JSON ist, das die Konfiguration erwartet.

Fallstricke beim ersten Start

Problem Ursache Lösung
Token aus .env wird abgelehnt InfluxDB-Init-Variablen gelten nur für ein leeres Volume Mit docker compose down -v zurücksetzen oder in der Oberfläche ein neues Token erstellen
Telegraf: connection refused zu localhost:8086 Falscher Hostname innerhalb der Container http://influxdb:8086 verwenden
Dashboard zeigt "No data" Topic-Präfix in .env weicht vom Veröffentlichten ab Mit mosquitto_sub -t "connectmq/demo/a1b2c3/#" -v vergleichen
Telegraf: Topic-Parsing-Fehler Präfixtiefe geändert, tags-Muster aber nicht Anzahl der _-Segmente an die Topic-Ebenen anpassen
Fehler bei der Grafana-Datenquelle Token oder Org passen nicht Seite der Datenquelle prüfen; die Werte stammen aus .env
Stack funktioniert, aber Daten verschwinden nach down -v Volumes gelöscht docker compose down ohne -v verwenden

Wechsel zu einem privaten Broker

Für echte Anlagen ändert sich nur .env. Richten Sie den Stack auf einen verwalteten MQTT-Broker wie ConnectMQ:

MQTT_SERVER=ssl://broker.connectmq.com:8883
MQTT_TOPIC_PREFIX=connectmq/factory1/production
MQTT_CLIENT_ID=YOUR_CLIENT_ID
MQTT_USERNAME=YOUR_USERNAME
MQTT_PASSWORD=YOUR_PASSWORD

Folgt Ihr Werk einem Unified Namespace (UNS) nach ISA-95, etwa acme/werk-stuttgart/montage/linie-1/..., setzen Sie MQTT_TOPIC_PREFIX auf den Teilbaum des Standorts und passen das tags-Muster an die zusätzlichen Ebenen an; so landen Area und Linie direkt als Tags in InfluxDB.

Das Zertifikat stammt von Let's Encrypt, Telegraf vertraut ihm also ohne zusätzliche TLS-Einstellungen. Führen Sie erneut docker compose up -d aus, um den Telegraf-Container mit den neuen Werten neu zu erstellen. Stellen Sie Grafana außerdem hinter einen Reverse Proxy mit HTTPS, bevor Sie es über Ihren Rechner hinaus erreichbar machen, und sichern Sie das Volume influxdb-data.

Wenn das Dashboard steht, ergänzen Sie Grafana-Alarme für IoT-Sensordaten auf denselben Abfragen. Für eine breitere Auswahl an Clients auf der Geräteseite siehe den Leitfaden zu MQTT-Client-Bibliotheken; die Docker-Compose-Dokumentation behandelt Healthchecks und Umgebungsdateien im Detail.

Starten Sie mit ConnectMQ

Nutzen Sie den öffentlichen MQTT-Broker, um den Stack noch heute mit simulierten Daten hochzufahren. Für die Produktion betreibt ConnectMQ einen vollständig verwalteten MQTT-Broker mit TLS, MQTT 5 und einem Portal, in dem Sie Topics live beobachten können, bevor Telegraf sie überhaupt sieht. Erstellen Sie unter app.connectmq.com einen kostenlosen Serverless-Broker ohne Kreditkarte und fügen Sie die Zugangsdaten in .env ein. Wenn Sie Hosting-Optionen abwägen, lesen Sie unseren Leitfaden zum Cloud-MQTT-Broker.

Häufig gestellte Fragen

Kann ich den MQTT-Broker in derselben Docker-Compose-Datei betreiben?

Das ist möglich, doch ein gemeinsam genutzter, verwalteter MQTT-Broker ist meist einfacher zu betreiben und erlaubt anderen Consumern, dieselben Daten zu nutzen. Ihn außerhalb von Compose zu halten bedeutet außerdem, dass ein Neustart des Stacks Ihre Geräte nie unterbricht.

Funktioniert dieses TIG-Stack-Setup mit Docker Compose auch mit InfluxDB 3?

Nicht unverändert. InfluxDB 3 verwendet ein anderes Image, ein anderes Einrichtungsverfahren und andere Abfragesprachen; die Init-Variablen und Flux-Abfragen hier gelten für InfluxDB 2.7.

Wie füge ich weitere Dashboards hinzu?

Legen Sie zusätzliche Dashboard-JSON-Dateien in grafana/dashboards ab. Grafana übernimmt sie über den File-Provider automatisch.

Wie viel Speicherplatz belegen die Daten?

Das hängt von der Anzahl der Serien und der Nachrichtenrate ab. Die 30-tägige Aufbewahrung des Buckets begrenzt das Wachstum; senken Sie sie oder führen Sie ein Downsampling älterer Daten durch, wenn der Speicher knapp ist.

Verwandte Artikel

Die besten MQTT-CLI-Tools zum Testen, Skripten und Debuggen

Ein praxisnaher Vergleich von mosquitto_pub/sub, MQTTX CLI, HiveMQ MQTT CLI, der MQTT.js-CLI, curl und mqttui – mit demselben Test gegen broker.connectmq.com, damit Sie das richtige Tool zum Skripten und Debuggen wählen.

8 Min. Lesezeit

Alle Artikel →

Ihr privater MQTT-Broker ist nur wenige Klicks entfernt

Konto anlegen, Broker-Zugangsdaten erhalten und das erste Gerät verbinden — ohne Server, die installiert, gepatcht oder skaliert werden müssen.