Back to guidesGuide

Prometheus for system metrics (cross-platform)

A practical foundation for scraping targets and validating stack health across Windows, Linux, macOS, and Docker.

Deploy Prometheus and validate operational metrics with a reproducible workflow, independent of your operating system.

Created: April 5, 2026

Published: April 5, 2026

Estimated time16 min
LevelBeginner
Before you startDocker and Docker Compose installed on your machine.
PlatformsDocker
WhatsAppXLinkedIn

Docker

This guide runs as a Docker-based lab. Use the Compose and configuration snippets in the article as the primary source of truth, and do not assume native OS support unless it is explicitly documented.

Docker and Docker Compose installed on your machine.At least one service exposing `/metrics` or an exporter you can scrape.Ports 9090 and 9100 free for the local lab.
Lab bootstrap
docker compose config
Stack start
docker compose up -d --build
Validation
docker compose ps
Prometheus is still one of the most direct ways to start with metrics because its model is simple: discover targets, scrape endpoints, and make queries available for alerts or dashboards. For local development or labs, Docker Compose gives you a clean and repeatable bootstrap.

Minimal lab architecture

  • One Prometheus container with a config file mounted from disk.
  • An initial target. This can be your app or an exporter such as node-exporter.
  • Basic persistence so you do not lose series on every restart.
What this setup optimizes for

This guide is not about high availability. The goal is a reliable local foundation for querying metrics and understanding the end-to-end flow.

Create the stack with Docker Compose

docker-compose.yml
services:
  prometheus:
    image: prom/prometheus:v2.54.1
    container_name: prometheus
    command:
      - --config.file=/etc/prometheus/prometheus.yml
      - --storage.tsdb.path=/prometheus
      - --web.enable-lifecycle
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus_data:/prometheus

  node-exporter:
    image: prom/node-exporter:v1.8.2
    container_name: node-exporter
    ports:
      - "9100:9100"

volumes:
  prometheus_data:

Prometheus scrapes a simple exporter first so you can validate the pipeline before pointing it at your application.

1

Define the scrape file

Create a `prometheus/` directory next to `docker-compose.yml`.

Use a short `scrape_interval` for the lab and add the exporter target so ingestion is easy to validate.

prometheus/prometheus.yml
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: "prometheus"
    static_configs:
      - targets: ["prometheus:9090"]

  - job_name: "node"
    static_configs:
      - targets: ["node-exporter:9100"]
2

Start the stack

Run `docker compose up -d` and wait until Prometheus and node-exporter are healthy or running.

Open `http://localhost:9090/targets` and verify both jobs show as UP.

command
docker compose up -d

Validate that metrics are queryable

Do not call the deployment finished until you run specific queries. Targets tells you scraping works; Graph proves you already have useful data.

  • Query `up` to list active targets.
  • Query `rate(node_cpu_seconds_total[5m])` to validate exporter series.
  • Check `prometheus_tsdb_head_series` to understand how much data you are already storing.

Checklist before moving beyond the lab

  • Prometheus starts with valid config and no parse errors.
  • Targets stay UP consistently.
  • Persistence is mounted so series survive restarts.
  • You already have a plan for auth or secrets on sensitive endpoints.

Add your first real service

Once the lab works, replace the initial exporter or add a new job for your application. If you use OpenTelemetry Collector, Prometheus can scrape the collector endpoint or service-specific exporters.

Do I need service discovery for a first test?

No. Start with `static_configs` until the model is clear. Dynamic discovery becomes useful once the environment is less manual.

What if every target is DOWN?

Check networking and DNS names inside Docker Compose first. In local labs the most common mistake is using `localhost` instead of the service name between containers.

Recommended next step

The natural next step is wiring this Prometheus instance into Grafana and building a minimal host or application health dashboard.

More related reads

More related reads

Metrics~45 min

Reduce Prometheus cardinality spikes with OpenTelemetry limits before the TSDB burns

Created: August 28, 2026 · Published: August 28, 2026

Learn how to find metrics that create runaway cardinality, separate SDK protection from real Prometheus cost, and apply safe mitigations in instrumentation, the Collector, and scrape config.

Linux
Advanced
Read guide
Metrics~45 min

Monitor controller-runtime without melting the Kubernetes API server

Created: August 27, 2026 · Published: August 27, 2026

Learn how to monitor Kubernetes controllers built with controller-runtime using Prometheus, workqueue metrics, API server signals, promtool rules, and canary validation.

LinuxDocker
Advanced
Read guide
Metrics~40 min

Fix Kubernetes memory alerts without falling for the page cache trap

Created: August 26, 2026 · Published: August 26, 2026

Learn how to redesign Kubernetes memory saturation alerts by comparing usage, working set, RSS, cache, limits, OOMKilled events, and promtool validation.

LinuxDocker
Intermediate
Read guide