Productivity

Prometheus Node Exporter Docker Compose 2GB VPS Memory Setup

Prometheus Node Exporter Docker Compose 2GB VPS Memory Setup

Running a full Prometheus stack on a 2GB VPS is, by default, a slow-motion disaster. The stock configuration consumes 600–900MB of RAM before you’ve scraped a single metric. But with a properly structured Docker Compose setup, you can run a prometheus node exporter docker compose 2gb vps memory optimization low resource setup that actually fits your hardware — and still leaves meaningful headroom for the workloads you’re trying to monitor.

This matters in 2026 because cloud costs haven’t dropped the way everyone predicted. Budget VPS instances at Hetzner, DigitalOcean, and Vultr still sit at the $4–$12/month tier for 2–4GB RAM nodes. Teams running small production services — hobby SaaS, staging environments, edge deployments — need observability without paying $40/month just to run monitoring infrastructure. The economics force efficiency.

The core argument: a properly tuned Prometheus stack on 2GB can stay under 350MB of working RAM. Not by cutting corners, but by understanding which default settings are catastrophically wasteful for small deployments.

Key Takeaways

  • A default Prometheus installation consumes 300–600MB RAM on its own; tuning --storage.tsdb.retention.time and scrape intervals cuts this to under 150MB on a 2GB VPS.
  • Node Exporter’s memory footprint is modest at roughly 20–30MB, but the number of enabled collectors matters — disabling unused collectors reduces CPU overhead by 15–25%.
  • Docker Compose resource limits (mem_limit, memswap_limit) are the single most important guard against OOM kills in constrained environments.
  • A fully tuned stack can achieve complete system visibility while consuming under 350MB total across all monitoring containers.

Why Default Configs Fail at 2GB

Prometheus was built by SoundCloud engineers to monitor large-scale infrastructure. The defaults reflect that origin. By default, Prometheus retains 15 days of TSDB data, runs scrape intervals at 15 seconds, and keeps query chunks loaded in memory for fast access.

On a 16GB dedicated server, that’s fine. On a 2GB VPS hosting your actual application, that’s a resource conflict waiting to crash production.

Node Exporter’s situation is different. The binary itself is lean — typically 20–30MB RSS. The problem is collector count. Out of the box, Node Exporter enables 30+ collectors, including several (perf, buddyinfo, drbd) that are irrelevant to most Linux VPS environments and add unnecessary overhead with nothing to show for it.

The Docker layer adds another layer of risk. Without explicit resource constraints in your docker-compose.yml, containers compete for the host’s memory pool with no guardrails. A Prometheus TSDB flush during a high-write period can spike memory temporarily — and on a 2GB host, that spike can OOM-kill your application container.

The pressure intensified through 2025–2026 as teams started running more services per VPS: containerized apps, databases, reverse proxies, and monitoring. The monitoring stack used to be an afterthought. It can’t be anymore.


The Three Levers That Actually Matter

Prometheus TSDB: The Real Memory Driver

TSDB memory consumption ties directly to three variables: retention period, number of active time series, and scrape interval. According to Prometheus documentation and community benchmarks in the Prometheus GitHub discussions (2025), each active time series consumes roughly 1–3KB of RAM in the write-ahead log (WAL).

A typical Node Exporter instance exposes 800–1,200 metrics. Multiply by a 15-day retention window and 15-second scrapes, and you’re holding a significant dataset in memory. The fix is direct:

command:
  - '--storage.tsdb.retention.time=3d'
  - '--storage.tsdb.wal-compression'
  - '--query.max-concurrency=2'
  - '--web.max-connections=10'

Cutting retention to 3 days — sufficient for immediate alerting and dashboards, with longer data sent to a remote write endpoint if needed — drops Prometheus RSS from roughly 450MB to under 130MB in documented community tests. WAL compression alone saves 30–40% of disk I/O, which indirectly reduces memory pressure from page cache.

Node Exporter: Surgical Collector Selection

For a typical Linux VPS running containerized apps, the essential collector set is small:

command:
  - '--collector.disable-defaults'
  - '--collector.cpu'
  - '--collector.meminfo'
  - '--collector.diskstats'
  - '--collector.filesystem'
  - '--collector.netdev'
  - '--collector.loadavg'
  - '--collector.uname'

Disabling the 20+ irrelevant collectors (arp, bcache, bonding, conntrack, drbd, edac, fibrechannel, hwmon, infiniband, ipvs, mdadm, mountstats, nfs, nfsd, perf, powersupplyclass, pressure, rapl, schedstat, selinux, sockstat, softnet, thermal, timex, udp_queues, xfs, zfs) reduces CPU cycles per scrape noticeably. The Node Exporter GitHub issue tracker documents 15–25% CPU reduction in resource-constrained environments after disabling default collectors.

Docker Compose Resource Limits: The Safety Net

This is where most guides stop short. Setting Prometheus flags is necessary but not sufficient. Without Docker-level memory limits, a misconfigured query or unexpected cardinality explosion can take down the entire host.

services:
  prometheus:
    image: prom/prometheus:v2.51.0
    mem_limit: 256m
    memswap_limit: 256m
    restart: unless-stopped

  node-exporter:
    image: prom/node-exporter:v1.8.0
    mem_limit: 64m
    memswap_limit: 64m
    restart: unless-stopped

Setting memswap_limit equal to mem_limit disables swap for the container. That forces the OOM killer to act quickly rather than degrading performance slowly through swap thrashing. On a 2GB VPS, slow swap death is worse than a clean container restart.


Default Stack vs. Tuned Setup: The Numbers

CriteriaDefault StackTuned 2GB Setup
Prometheus RAM400–600MB120–150MB
Node Exporter RAM30–50MB20–25MB
Retention Period15 days3 days
Scrape Interval15s30s
Docker Memory LimitsNone256MB / 64MB
WAL CompressionDisabledEnabled
Collector Count30+8–10
Total Monitoring Overhead430–650MB140–180MB

The tuned setup leaves ~1.8GB for the application on a 2GB host. The default setup leaves barely 1.3GB — before any memory spike.


Three Scenarios Worth Planning For

Staging environments sharing a node with app containers. This is the most common 2026 use case. Teams run a containerized Node.js or Python app alongside monitoring. With a tuned setup, monitoring overhead drops from roughly 30% of host RAM to under 10%. The 30-second scrape interval is fine for staging — 15-second granularity isn’t worth the cost when nobody’s getting paged at 3am.

Use Docker Compose depends_on with health checks so Prometheus only starts after your application container is healthy. This prevents monitoring from consuming startup RAM that the app needs.

Edge deployments on ARM-based VPS instances. Hetzner’s CAX11 (Ampere ARM, 4GB) and similar ARM VPS options are popular in 2026 for cost reasons. Node Exporter builds for linux/arm64 are official and well-maintained. The same tuning applies — though ARM instances often have faster memory but slower single-core performance, making the CPU savings from selective collectors more impactful per dollar.

Pin specific image digests in your docker-compose.yml rather than using latest. Unexpected Node Exporter updates have broken --collector.disable-defaults flag parsing in minor releases historically.

Monitoring with alerting on a budget. Adding Alertmanager to this stack costs roughly 30–40MB of additional RAM. That keeps the full monitoring trio — Prometheus, Node Exporter, and Alertmanager — under 220MB. Still workable on 2GB.

One approach worth evaluating: Prometheus’s Agent Mode, stable since v2.40, is worth considering for setups where you only need remote write and no local querying. Agent Mode’s memory footprint runs 40–60% lower than full Prometheus, according to the Prometheus 2.40 release notes. If Grafana Cloud or another remote endpoint handles your dashboards, Agent Mode is the right call — not a compromise, just the correct tool.

This approach can fail when your remote write endpoint experiences latency or downtime. Without local TSDB, there’s no fallback. Budget setups relying entirely on Agent Mode should include a monitoring dead man’s switch or at minimum a local alerting buffer.


What to Do Next

Running a proper low-resource Prometheus setup in 2026 isn’t about compromise. It’s about correctness. The defaults were never designed for shared 2GB nodes.

The findings are consistent: TSDB retention and scrape interval tuning cuts Prometheus RAM by 60–70%. Selective collector configuration reduces Node Exporter CPU overhead by 15–25%. Docker mem_limit constraints prevent OOM cascade failures. Total tuned stack footprint sits under 220MB for Prometheus, Node Exporter, and Alertmanager combined.

Over the next 6–12 months, Prometheus Agent Mode adoption will likely accelerate. As remote write endpoints like Grafana Cloud, Mimir, and Thanos Receive become cheaper, the case for running full local TSDB on small VPS instances weakens. The practical sweet spot will be Agent Mode locally with 7-day remote retention — minimal local RAM, full historical data elsewhere.

The immediate action is straightforward: audit your current docker-compose.yml for missing mem_limit fields. That single omission is the most common reason monitoring takes down production on small hosts. Fix that first, then tune the rest.

What’s your current Prometheus retention setting — and has it caused problems on constrained nodes? That’s the real diagnostic question worth answering.

References

  1. Prometheus with Docker Compose: The Complete Setup Guide | Last9
  2. Prometheus with Docker Compose: Guide & Examples
  3. I built a Prometheus exporter for Docker Compose health monitoring - DEV Community

Photo by GuerrillaBuzz on Unsplash