Files
laermsensor-stack/README.md
T
admin eeab1ddbe5 README: Netz-Namen fuer readarchive-stack erklaert
Das docker-compose.yml des Haupt-Stacks deklariert kein Netz - Compose
legt <projektname>_default selbst an. Bei Portainer ist der Projektname
der Stack-Name, der in readarchive-stack.yml eingetragene Wert
noisesensors_default passt also nur, wenn das Stack auch so heisst. Sonst
bricht der Lauf mit "declared as external, but could not be found" ab.

Dazu als Option das Umbenennen des Default-Netzes (fester Name, unabhaengig
vom Stack-Namen) und der Hinweis, dass ein networks: an einem Service
dessen automatische Zuordnung aufhebt - wer dort etwas eintraegt, muss
default mit auffuehren.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-02 14:24:00 +00:00

12 KiB

Projekt Lärm-Sensoren

Installation der Container

Dateien

Directory-Struktur

Die Datei noise.tgz enthält die folgenden Dateien und Verzeichnisse:

<LOCALDIR>
|
+- <d>noisesensors
       |
       +- <f>docker-compose.yml
       +- <f>readarchive-stack.yml
       +- <d>log
       +- <d>data
       |  +- <d>mongo
       |  |  +- <d>data  
       |  |  +- <d>entries
       |  |  |  +- <f>create.js
       |  + <d>influx
       |  |  + <d>data   

<f>: file,  <d>: directory       
  • docker-compose.yml
    enthält die Anweisungen für die Docker-Container. Dies kann so an das aktuelle Portainer-Stack angehängt werden.
  • readarchive-stack.yml
    eigenes, kleines Stack für den Einmal-Lauf readarchive (siehe unten). Gehört bewusst nicht ins Haupt-Stack, weil es kein Dauerdienst ist.
  • log
    Ablage für die Logdateien der einzelnene Container (noise.log, sensorapi.log und readin.log) . Diese werden täglich komprimiert. Es werden Versionen für 7 Tage aufgehoben.
  • data
    hier darunter befinden sich alle Daten, sowohl die Datenbanken als auch Konfigurationen. Außerdem werden jeweils die laufend eingelesenen Daten als actdata.json abgelegt. Diese werden bei jedem neuen Einlesen wieder überschrieben.
  • data/mongo
    Verzeichnis für die Mongo-Datenbank
  • data/mngo/data
    hier befinden sich die eingelesenen Daten
  • data/mongo/entries
    hier liegt die Datei create.js, mit deren Hilfe bei ersten Start der Datenbank die Collections und die Indexe erzeugt werden.
  • data/influx
    Verzeichnis für die Influx-Datenbank
  • data/influx/data
    Hier dann die eingelesenen Daten

Aufrufe

Entpacken des Tar-Files noise.tgz in einem beliebigen Verzeichnis (das Direktoty noisesensors wird angelegt). Der komplette Pfad zu dem Verzeichnis (also ab root) muss in der Environmentvariablen LOCALDIR hinterlegt werden.

Nun das docker-compose.yml in das Portainer-Stack einfügen. Zusätzlich folgende Environment-Variablen festlegen:

DOCKER_INFLUXDB_INIT_USERNAME=<username>
DOCKER_INFLUXDB_INIT_PASSWORD=<passwort>
DOCKER_INFLUXTOKEN=<token>
MONGO_ROOT_USERNAME=<username1>
MONGO_ROOT_PASSWORD=<passwort1>
LOCALDIR=<directory, in die das .tgz entpackt wurde>
STORE=influx

<username>, <passwort>, <username1>, <passwort1> und <token> sind anzupassen.

Danach einloggen in das Docker-Registry auf citysensor.de:

docker login docker.citysensor.de

Einloggen mit Username und Passwort (siehe mail), anschließend kann das Portainer-Stack gestartet werden (die Container werden beim ersten mal automatisch von docker.citysensor.de herunter geholt).

Damit sollte dann Alles laufen. Das Programm holt alle 5min die neuesten Daten von sensor.community ab und speichert die Messwerte in der InfluxDB und die Metadaten des Sensors in der Mongo-Datenbank.
Das Logfile kann via tail -f log/noise.log im Verzeichnise noisesensors mitgeschrieben werden.

Container

  • readin
    Über diesen Container werden alle 5 min. die aktuellen Daten von sensor.community abgeholt und in den beiden Datenbanken gespeichert

  • readarchive
    Gegenstück zu readin: liest rückwirkend die Tagesdateien von archive.sensor.community ein, um Lücken zu füllen. Kein Dauerdienst, sondern ein Lauf mit Parametern — deshalb steht er nicht im Haupt-Stack, sondern in der eigenen Datei readarchive-stack.yml.

Auf der Kommandozeile mit Argumenten:

docker compose -f readarchive-stack.yml run --rm readarchive \
       -t noise -s 2026-07-22 -e 2026-07-23 -d influx

Im Portainer als eigenes Stack anlegen (Inhalt von readarchive-stack.yml) und die Parameter unten als Environment variables eintragen — docker compose run hat dort kein Gegenstück, aber readFromcsv.js liest jeden Parameter auch aus einer Env-Variablen:

CLI Env Default
-s START gestern
-e END Startdatum + 1 Tag (exklusiv)
-t TYP noise
-d DBASE both, in der Stack-Datei auf influx vorbelegt

Deploy the stack startet den Lauf, der Container endet danach und bleibt als „Exited" stehen. Für den nächsten Zeitraum nur die Variablen ändern und Update the stack. Der Haupt-Stack wird dabei nicht angefasst.

Beide Wege brauchen dieselben Zugangsdaten und LOCALDIR — auf der Kommandozeile aus einer .env neben der Datei, im Portainer aus den Stack-Variablen. Auch mit -d influx wird Mongo gebraucht, dort liegen die Metadaten der Sensoren.

Der Netz-Name ist die Stolperstelle. Das docker-compose.yml des Haupt-Stacks deklariert kein Netz — Compose legt für jedes Projekt automatisch <projektname>_default an und hängt alle Services hinein; daher funktioniert MONGOHOST: mongodb. Bei Portainer ist der Projektname der Stack-Name. Heißt das Stack dort noisesensors, passt der in readarchive-stack.yml eingetragene Wert noisesensors_default; heißt es laerm, muss dort laerm_default stehen, sonst bricht der Lauf ab:

network noisesensors_default declared as external, but could not be found

Vor dem ersten Lauf also im Portainer unter Networks nachsehen (oder docker network ls) und den Namen in readarchive-stack.yml angleichen. Das Netz wird nur an einer Stelle erzeugt — im Haupt-Stack implizit. Es auch dort als external zu deklarieren, führt dazu, dass es niemand mehr anlegt.

Option: fester Netz-Name. Wer die Abhängigkeit vom Stack-Namen loswerden will, benennt im Haupt-Stack das Default-Netz um:

networks:
  default:
    name: noisesensors_net

Kein Service braucht dafür einen eigenen networks:-Eintrag — die automatische Zuordnung bleibt, das Netz heißt nur fest noisesensors_net, und in readarchive-stack.yml steht dieser Name statt <stack-name>_default. Der Preis: Beim Umstellen wechseln alle Container das Netz und werden neu erzeugt, Mongo und Influx sind also kurz weg. Die Daten liegen auf Bind-Mounts und bleiben unangetastet — trotzdem gehört das in ein Wartungsfenster und nicht nebenbei erledigt.

Umgekehrt gilt: Ein networks: an einem Service hebt dessen automatische Zuordnung auf. Wer dort etwas einträgt — etwa um noise zusätzlich ins Traefik-Netz zu hängen —, muss default mit aufführen, sonst erreicht der Service die übrigen Container des Stacks nicht mehr.

Ein Tag dauert etwa zwei Minuten. Schlägt ein Influx-Write fehl, werden die betroffenen Sensoren am Ende aufgelistet und der Exit-Code ist ≠ 0 (im Portainer als „Exited (1)" sichtbar).

  • logrotate
    Mit Hilfe dieses Containers werde die Log-Files im Unterverzeichnis log täglich rotiert. Es werden 7 Versionen behalten, ältere gelöscht.

  • sensorapi
    Über diesen Container werde die Daten aus der Mongo-Datenbank ausgelesen, aufbereitet und als JSON- oder CSV-Datei ausgegeben.

  • noise
    Mit diesem Container wird die Grafik aufbereitet. Auch kann darüber die API (im Container sensorapi) angesprochen und die Daten abgerufen werden. (Für die Parameter der Anfrage siehe die extra Beschreibung Laerm_API). Dieser Container sollte von außen über einen Domainnamen erreichbar sein. Ansonsten hört er auf Port 3003 auf HTTP-Anfragen.

  • mongodb
    Die Mongo-Datenbank. Es gibt eine Datenbank namens sensor_data. Diese hat folgende Collections:

    • properties
      Hier liegen für alle Sensoren die Metadaten (wie Ortskoordinaten, Typ, Zeitpunkt der letzten Übertragung etc.)
    • statistics
      Dient nur Kontrolle, schreibt verschiedenen Statistikdaten wie Dauer des Einlesens, Dauer des Speicherns in den DBs etc.
      Zugriff:
      Am Besten über das Programm MongoDB Compass. Zugangsdaten entprechend der im Portainer hinterlegten.
  • influxdb
    Die Influx-Datenbank. Hier werden in dem Bucket sensor_data die reinen Messwert der einzelnen Sensoren gespeichert.
    Zugriff:
    http://<server>:8086
    Logindaten: Entsprechen der im Portainer hinterlegten.

Sourcen für die Container

Das gesamte Projekt ist im GitHub unter laermsensor-stack abgelegt. Für jeden der 4 Container existiert darunter ein Verzeichnis: readin, readarchive, sensorapi und noise. In diesen Verzeichnissen sind alle benötigten Sourcen enthalten.

Daneben gibt es common mit den Modulen, die sich readin und readarchive teilen: mongo.js, influx_post.js, logit.js und statistics.js. Sie lagen früher in beiden Komponenten doppelt und sind auseinandergelaufen. Wer dort etwas ändert, ändert es für beide — nach einer Änderung also beide Container neu bauen.

Sollte was geändert werden, so muss mit deploy.sh der Container neu erzeugt und auf die Registry (siehe oben) gepushed werden. Der Build-Kontext von readin und readarchive ist wegen common/ das Wurzelverzeichnis des Repositories; deploy.sh wechselt selbst dorthin und kann aus dem Komponentenverzeichnis aufgerufen werden.

deploy.sh nimmt optional ein Tag als Argument:

./deploy.sh              # nur :latest
./deploy.sh 2026-08-01   # :2026-08-01 und zusätzlich :latest

Ein Tag mitgeben. Wird nur latest gepusht, überschreibt jeder Build den vorherigen Stand und es gibt keinen Weg zurück (siehe Update eines laufenden Stacks).

Das Verzeichnis noisesensors ist nur dummy, es spiegelt die Dateistruktur für das aktuelle Stack ab, wie oben beschrieben (wird mit Hilfe von noise.tgz erzeugt).

Update eines laufenden Stacks

Betrifft eine Installation, die bereits läuft und auf einen neueren Stand gebracht werden soll.

1. Rollback-Möglichkeit sicherstellen

Vor allem anderen. Zeigt in der Registry nur latest auf das Image, existiert der laufende Stand nach dem Pull nirgends mehr. Prüfen, welche Tags es gibt:

curl -H "Authorization: Basic <auth aus ~/.docker/config.json>" \
     https://docker.citysensor.de/v2/readin/tags/list

Fehlt ein benanntes Tag für den laufenden Stand, ihn zuerst benennen und pushen. Das alte Image findet sich auf dem Build-Rechner meist noch unbenannt (docker images | grep readin):

docker tag <alte-image-id> docker.citysensor.de/readin:<datum-alt>
docker push docker.citysensor.de/readin:<datum-alt>

2. docker-compose.yml im Portainer angleichen

Den Stand aus noisesensors/docker-compose.yml dieses Repositories übernehmen. Zu beachten:

  • Zwingend bei einem Update von einem Stand vor August 2026: das Volume von readin muss auf /opt/app/readin/data zeigen, nicht mehr auf /opt/app/data. Das Layout im Image spiegelt seit der Einführung von common/ das Repository. Bleibt der alte Pfad stehen, schreibt readin aktdata.json in die Container-Schicht statt auf den Host.
  • Der Service readarchive gehört nicht mehr ins docker-compose.yml. Steht er dort noch (mit profiles: ["tools"]), kann er beim Update entfallen — er wird durch das eigene Stack readarchive-stack.yml ersetzt.
  • Nicht aufnehmen: ein Mount auf /etc/influxdb2. Das Entrypoint von influxdb legt dort beim Setup das CLI-Profil default an. Ist bereits eines vorhanden, scheitert der Setup — und das Entrypoint löscht daraufhin influxd.bolt und engine/ im Datenverzeichnis und startet neu. Weil der Mount das Aufräumen überlebt, wiederholt sich das endlos und der Datenbestand ist bei jeder Runde weg.

3. Nur den geänderten Container ziehen

Nicht den ganzen Stack neu starten — Mongo und Influx bleiben unangetastet:

docker compose pull readin
docker compose up -d readin

Im Portainer entspricht das dem Aktualisieren des Stacks mit Re-pull image and redeploy.

4. Verifizieren

Der nächste Lauf kommt binnen fünf Minuten:

tail -20 <LOCALDIR>/noisesensors/log/readin.log
ls -l  <LOCALDIR>/noisesensors/data/aktdata.json

Erwartet werden Influx-Write-Time und Program end sowie ein frischer Zeitstempel an aktdata.json — letzterer belegt, dass der Volume-Pfad stimmt.

5. Rollback

Image-Tag im Stack auf den in Schritt 1 gesicherten Stand setzen, die Volume-Zeile auf den alten Pfad zurückdrehen, redeploy.

Versionen

Version Datum Bemerkung
1.0.0 2023-11-30
2.0.0 2026-07-25 Anpassung an Stack-Änderungen
2.1.0 2026-08-01 readarchive dazu, gemeinsame Module unter common/, Zeitstempel in UTC
2.1.1 2026-08-02 readarchive als eigenes Stack (readarchive-stack.yml)