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

Logs~40 min

Build incident timelines from logs, metrics, and traces without making up the missing parts

Created: May 2, 2026 · Published: May 2, 2026

Learn how to reconstruct a real incident from Prometheus, Loki, and distributed traces without getting lost in noise, clock skew, or confident storytelling.

LinuxDocker
Intermediate
Read guide
Logs~40 min

Debug Vector pipelines before retries and buffers hide the real bottleneck

Created: May 1, 2026 · Published: May 1, 2026

A practical guide to using Vector internal metrics, config validation, and isolation tests when logs arrive late, get retried too often, or vanish.

LinuxDocker
Intermediate
Read guide
Metrics~40 min

Reduce Prometheus cardinality spikes without blinding your alerts

Created: April 30, 2026 · Published: April 30, 2026

A practical guide to spotting when Prometheus is swelling because of unstable labels, cutting cardinality in the right layer, and validating that your alerts still cover the real incident.

LinuxDocker
Advanced
Read guide