Abstract teal and amber illustration representing Prometheus metrics collection and monitoring

Prometheus

Prometheus

Prometheus is an open-source monitoring system that pulls metrics from your services on a set schedule and stores them in its own time-series database, queryable with PromQL. It ships with only a bare-bones query browser, not real dashboards, which is why almost every self-hosted setup runs Grafana alongside it rather than instead of it.

License: Apache License 2.0, confirmed directly from the LICENSE file in the prometheus/prometheus GitHub repo, not assumed from a badge. That’s held steady: Prometheus has never relicensed, and it’s a Cloud Native Computing Foundation project rather than owned by a company that could change that later, the way Grafana moved to AGPLv3 in 2021.

Quick facts: Official site prometheus.io · GitHub prometheus/prometheus, 64,000+ stars · Docker image prom/prometheus on Docker Hub, 1.9 billion+ pulls (also mirrored on Quay.io) · default port 9090 · default retention 15 days.

What Prometheus actually does

Prometheus started as an internal tool at SoundCloud in 2012 and became the Cloud Native Computing Foundation’s second hosted project in 2016, right after Kubernetes, according to Prometheus’s own overview docs. The core mechanic hasn’t changed: on a fixed interval, the server reaches over HTTP to every target in its config, pulls whatever metrics it exposes, tags each point with labels, and appends it to a local time-series database, one file per series, no external database needed. That pull model is the opposite of most logging tools, and it makes a dead target obvious: if Prometheus can’t reach it, the target shows as down instead of just going quiet.

A full deployment is really several small binaries: the server itself, exporters like node_exporter and cAdvisor translating host or container stats into something scrapable, and Alertmanager routing the alerts Prometheus’s rules fire. None of that is required to start, a single container scraping itself is a valid deployment, but most homelab stacks run node_exporter and Alertmanager alongside it anyway.

Installing Prometheus with Docker

The official image is prom/prometheus on Docker Hub, the same one Prometheus’s installation docs point to, alongside a Quay.io mirror. A docker-compose setup with a named volume for the data directory is the practical starting point, since the container has nothing worth keeping without one.

services:
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    restart: unless-stopped
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus

volumes:
  prometheus_data:
  1. Create a prometheus.yml file in the same directory first (see the scrape config below), since it’s mounted in at startup, not generated afterward.
  2. Save the compose file above as docker-compose.yml and run docker compose up -d.
  3. Open http://your-server-ip:9090 and check Status → Targets to confirm Prometheus is scraping itself.
  4. Add real targets, node_exporter for host metrics or cAdvisor for container metrics, to scrape_configs and restart the container to pick up the change.
docker compose up -d

Security notes: Prometheus has no authentication, no user accounts, and no TLS on by default, confirmed from Prometheus’s own security documentation, which explicitly warns against exposing its HTTP endpoints to the public internet. Anyone who can reach port 9090 can read every metric it has stored. Put it behind a reverse proxy like Caddy if it needs to be reachable from outside your network, or keep it off the internet entirely with something like Tailscale.

Basic configuration: scrape configs and PromQL

Everything Prometheus scrapes is defined in the one YAML file passed via –config.file. A minimal version, scraping Prometheus itself plus a node_exporter container, looks like this:

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'node_exporter'
    static_configs:
      - targets: ['node-exporter:9100']

Each job_name groups one kind of target under static_configs, or a service-discovery block for anything more dynamic than a fixed host list. Once data is flowing, PromQL turns raw counters into something readable: rate(node_cpu_seconds_total{mode="idle"}[5m]) tracks CPU usage as a five-minute moving average. It’s a real query language with its own syntax, closer to a small functional language than SQL, and it’s the part that takes longest to feel natural.

Pairing Prometheus with Grafana

Prometheus and Grafana get bundled together so often it’s easy to assume picking one means skipping the other. They’re not competing for the same job: Prometheus collects, stores, and queries metrics; Grafana connects to it as a data source and turns those queries into dashboards, with its own alerting layer on top. Our Grafana fiche covers the visualization half; from the Prometheus side, the only setup needed is adding http://prometheus:9090 as a data source once both containers share a Docker network.

Prometheus’s own expression browser is fine for testing a query while writing a scrape config, but it has no saved dashboards and no alerting UI, which is the real answer to any “Prometheus vs Grafana” question: it’s not a choice between the two, just whether you stop at the expression browser or add Grafana on top. cAdvisor is the usual third piece in a homelab watching Docker containers, exposing per-container CPU, memory, and network stats the same way node_exporter exposes host stats, even if those containers run through Portainer.

Prometheus and its alternatives

Prometheus isn’t the only self-hosted option for collecting metrics, and it isn’t always the right one. Each deserves its own fiche rather than a few table cells, so this stays brief:

PrometheusInfluxDBVictoriaMetricsNetdata
Collection modelPull, scrapes targetsPush, data written inPull, or remote-write from PrometheusPush, agent-based, near-zero config
Query languagePromQLInfluxQL / FluxPromQL-compatibleBuilt-in charts, limited querying
DashboardsNone built in, pairs with GrafanaBasic UI includedNone built in, pairs with GrafanaReal-time, pre-built, no setup
Best forService metrics, alertingEvent logging, IoT seriesLong-term storage, lower costZero-config single-host monitoring

Prometheus: pros and cons

  • Free and fully open source under Apache-2.0, with no single company able to relicense it later
  • Pull-based scraping makes a dead target obvious, and adding a new one is one YAML block away
  • PromQL is powerful enough for real alerting logic, not just static thresholds
  • Ships as a single static binary or container, no external database to stand up first
  • No dashboards or alerting UI of its own beyond the bare expression browser, Grafana is effectively required
  • No authentication or TLS by default, needs a reverse proxy or private network to expose safely
  • Local storage isn’t clustered, scaling past one node means manual sharding or a remote-write backend
  • PromQL has a real learning curve before scrape configs and alert rules feel natural

Hardware: Prometheus’s resource use tracks how many time series it’s storing and how often it scrapes them, not raw network traffic; its own docs put local storage at roughly 1-2 bytes per sample. A homelab scraping a handful of exporters every 15 seconds runs fine on a small VM with 1-2 CPU cores and a couple gigs of RAM, though that climbs fast with dozens of targets or much shorter intervals. Our homelab setup guide for beginners covers picking hardware for the stack as a whole.

FAQ

Is Prometheus free to use?

Yes, Apache-2.0, free for any use including commercial, with no paid tier since no single company owns the project. Some vendors sell hosted, Prometheus-compatible services, but the core project has nothing to buy.

Do I need Grafana to use Prometheus?

No, but almost everyone runs both. Prometheus includes a bare expression browser for testing PromQL queries, with no persistent dashboards or alerting UI. Grafana is the near-universal choice for the visualization layer Prometheus doesn’t provide.

How long does Prometheus keep data by default?

15 days, set by the –storage.tsdb.retention.time flag, confirmed from Prometheus’s own storage docs. Easy to extend for a homelab with disk to spare, or cap by size instead with –storage.tsdb.retention.size.

Can Prometheus monitor Docker containers directly?

Not on its own, it needs an exporter in between. cAdvisor exposes per-container CPU, memory, and network metrics Prometheus can scrape, and node_exporter does the same for the host. Both run as their own containers alongside Prometheus.

Is Prometheus difficult to set up?

Getting the container running is close to trivial, one YAML file and docker compose up. What takes longer is writing scrape configs for more than a couple of targets, learning enough PromQL for a useful alert, and adding Alertmanager eventually, which is why we rate it Medium rather than Easy, same as Grafana.

Prometheus is the collection engine most self-hosted monitoring stacks are quietly built around, even when Grafana gets credit for the dashboard everyone actually looks at. Our homelab setup guide for beginners covers the Docker basics it runs on, and Uptime Kuma is worth running alongside it for the simpler question Prometheus isn’t built to answer: is this actually up right now. The Monitoring category rounds out the rest of the tooling here.