← Zurück zur Übersicht Prometheus & Grafana: Performance-Monitoring für Docker-Umgebungen

Prometheus & Grafana: Performance-Monitoring für Docker-Umgebungen

[WERBUNG: CONTENT OBEN]

Fliegst du im Blindflug?

Stell dir vor, du betreibst deine eigene Node.js-Backend-Infrastruktur – aber du hast keine Ahnung, wie viele HTTP-Requests gerade bearbeitet werden, wie hoch der RAM-Verbrauch ist oder welche API-Routen heimliche Performance-Fresser sind. Es ist, als würdest du ein Auto ohne Tachometer fahren.

In der Industrie ist das Duo Prometheus (Metrik-Sammler) und Grafana (Dashboards) der unbestrittene Goldstandard für Monitoring.

In diesem praxisbezogenen Tutorial bauen wir keine leere Infrastruktur auf: Wir verknüpfen eine Live Node.js-API direkt mit Prometheus und visualisieren die Daten wunderschön in einem Grafana-Dashboard. Alles läuft vollautomatisch per Docker Compose.

Vorbereitung: Psychologische Sicherheit

Bevor wir anfangen, Metriken und Konfigurationen wild durcheinander zu wirbeln, schützen wir dein System-Dateisystem. Wir starten bei Null in einer sauberen Sandbox.

Öffne dein Terminal und führe diese grundlegenden Befehle aus:

mkdir app-monitoring
cd app-monitoring

Ab jetzt arbeitest du ausschließlich in diesem Ordner.

Der Praxis-Code: API, Sammler und Dashboard

Wir kreieren vier Dateien: Die Basis unserer App (Package und Node-Code), eine Prometheus-Konfiguration und das krönende Docker-Compose-Netzwerk.

Bilde diese Architektur in deinem Ordner exakt nach:

app-monitoring/package.json:

{
  "dependencies": {
    "express": "^4.18.2",
    "prom-client": "^15.1.0"
  }
}

app-monitoring/server.js (Unsere Live-App, die Metriken ausspuckt):

const express = require('express');
const client = require('prom-client');
const app = express();

// Standard-Prometheus Parameter zur Erfassung von CPU- und RAM-Metriken
const collectDefaultMetrics = client.collectDefaultMetrics;
collectDefaultMetrics({ register: client.register });

// Ein eigener, intelligenter Zähler für eingehende Requests
const requestCounter = new client.Counter({
  name: 'api_requests_total',
  help: 'Die gesamte Anzahl an API-Anfragen auf unserem Server',
  labelNames: ['method', 'route', 'status_code']
});

// Middleware, die alle Router durchläuft und das Tracking triggert
app.use((req, res, next) => {
  res.on('finish', () => {
    requestCounter.labels(req.method, req.path, res.statusCode).inc();
  });
  next();
});

// Reguläre Routen
app.get('/shop', (req, res) => res.send('Willkommen im Shop!'));
app.get('/error', (req, res) => res.status(500).send('Ups! Etwas ging schief.'));

// DIESE Route sucht Prometheus heimlich alle 5 Sekunden auf, um die Metriken abzuholen
app.get('/metrics', async (req, res) => {
  res.set('Content-Type', client.register.contentType);
  res.send(await client.register.metrics());
});

app.listen(3000, () => console.log('✅ API mit Prometheus-Metriken läuft auf Port 3000'));

app-monitoring/prometheus.yml (Die Bauanleitung für das Sammeln von Daten):

global:
  scrape_interval: 5s # Alle 5 Sekunden wird gesammelt

scrape_configs:
  - job_name: "node_api"
    static_configs:
      # 'node_api' ist der Service-Name in unserem Docker-Setup
      - targets: ["node_api:3000"]

app-monitoring/docker-compose.yaml:

version: '3.8'

services:
  # Unsere Node.js Praxis-App
  node_api:
    image: node:18-alpine
    container_name: local_node_api
    working_dir: /app
    volumes:
      - ./server.js:/app/server.js
      - ./package.json:/app/package.json
    command: sh -c "npm install && node server.js"
    ports:
      - "3000:3000"

  # Prometheus ruft permanent "/metrics" von der node_api ab
  prometheus:
    image: prom/prometheus:latest
    container_name: local_prometheus
    restart: unless-stopped
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
    ports:
      - "9090:9090"
    depends_on:
      - node_api

  # Grafana bringt die faden Prometheus-Metriken in bunte Diagramme
  grafana:
    image: grafana/grafana:latest
    container_name: local_grafana
    restart: unless-stopped
    ports:
      - "3001:3000"
    depends_on:
      - prometheus

Startschuss: Infrastruktur entfesseln

Anstatt Container einzeln hochzufahren, bündeln wir unsere Kraft in einem Befehl.

docker compose up -d

⚠️ 📸 SCREENSHOT ANFRAGE: Hier einen Screenshot vom Terminal einfügen, der den Start der Container (local_node_api, local_prometheus, local_grafana) zeigt.

Der atemberaubende Test-Flow

Um unser neues System zu bewundern, produzieren wir etwas Test-Traffic auf unserer API:

  1. Öffne 3-4 mal in deinem Browser http://localhost:3000/shop
  2. Produziere künstliche Fehlermeldungen bei http://localhost:3000/error Dank unserer Dockerisierung fühlst du dich sofort wie bei den großen Cloud-Anbietern. In Grafana kannst du nun eine "Data Source" hinzufügen, dort als Hostname http://prometheus:9090 eingeben und hast ab sofort all deine Node.js Daten parat! Such in Grafana zum Beispiel mal nach dem Wert api_requests_total.

⚠️ 📸 SCREENSHOT ANFRAGE: Hier einen Screenshot von einem Grafana-Dashboard einfügen, das die api_requests_total Metrik grafisch darstellt.

Fazit

Mit einem einzigen docker-compose.yaml und einem klitzekleinen npm-Paket (prom-client) hast du dir den Industriestandard der Software-Überwachung lokal repliziert. Ohne blinde Setups – direkt am Praxisbeispiel!

[WERBUNG: CONTENT UNTEN]