iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
Need a server to try this on? Antihost offers Linux VPS plans with NVMe storage, full root access and a 14-day free trial.
A dependable Prometheus Compose stack needs three things wired correctly: a Prometheus service, a YAML configuration mounted at /etc/prometheus/prometheus.yml, and persistent storage mounted at /prometheus. Add exporters such as cAdvisor as additional Compose services, then scrape them by their Compose DNS names—not by localhost. The files and commands below produce a working baseline you can extend without losing time-series data on container restarts.
What the Compose stack does
Docker Compose is a tool for defining and running multi-container applications. In this setup, Compose creates a small monitoring network in which Prometheus collects metrics by scraping HTTP endpoints exposed by itself and by exporters. Prometheus provides the storage and query engine; an exporter exposes metrics about another system or service; Compose supplies repeatable startup, networking, volume, and logging behavior.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesThe smallest useful deployment has one service:
- Prometheus, listening on port 9090, reading a configuration file, scraping its configured targets, and writing time-series data under
/prometheus.
A fuller container-monitoring deployment adds cAdvisor, which exposes container metrics on port 8080. The official example also includes Redis on port 6379 and demonstrates Compose service dependencies. Grafana can be added as a separate visualization service, but it does not replace Prometheus or change how Prometheus performs scraping.
Recommended project layout
Keep the Compose file and Prometheus configuration together so the bind mount is unambiguous:
#1 Best Overall
prometheus-compose/
├── docker-compose.yml
└── prometheus.yml
Run every Compose command from the directory containing docker-compose.yml. A relative mount such as ./prometheus.yml is resolved from that working directory.
Minimal Prometheus-only docker-compose.yml
Use this baseline when you need Prometheus itself before adding exporters:
Free tools Windows power users keep installed
One-click scans. No signup required.
services:
prometheus:
image: prom/prometheus
command:
- --config.file=/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus-data:/prometheus
volumes:
prometheus-data:
The official container guidance uses port 9090, mounts the configuration at /etc/prometheus/prometheus.yml, and mounts persistent storage at /prometheus. The :ro suffix makes the configuration mount read-only from inside the container. The named volume is managed by Docker and survives replacement or restart of the Prometheus container.
Why the command explicitly names the configuration file
The command passes --config.file=/etc/prometheus/prometheus.yml, matching the mount target. This removes ambiguity if the image’s default path changes or if you later add more configuration files. The path on the left side of the bind mount is your host file; the path on the right is the path Prometheus reads inside the container.
Why the volume is not optional
Prometheus writes its time-series database beneath /prometheus. Without a named volume or bind mount at that path, data remains in the container’s writable layer and is lost when the container is removed or recreated. A restart that keeps the same container may appear to work, but a routine image update or docker compose up that replaces the container can erase the history.
Write prometheus.yml
Prometheus configuration is YAML. The global block supplies defaults, rule_files loads recording or alerting rules, and scrape_configs defines jobs and their targets.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: prometheus
static_configs:
- targets: ['prometheus:9090']
The 15-second values are defaults for this example. A scrape interval is a compromise: shorter intervals show changes sooner and create more samples, while longer intervals reduce collection frequency. Set a job-specific interval only when a target needs a different cadence.
Add cAdvisor as a scrape target
Extend the file with a second job:
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: prometheus
static_configs:
- targets: ['prometheus:9090']
- job_name: cadvisor
scrape_interval: 5s
static_configs:
- targets: ['cadvisor:8080']
This follows the official cAdvisor pattern: Prometheus is scraped every 15 seconds, while cAdvisor is scraped every 5 seconds. The target is cadvisor:8080 because cadvisor is the Compose service name and Compose supplies DNS for services on the project network.
Load recording and alerting rules
If you create rule files, declare them in the same configuration:
rule_files:
- /etc/prometheus/rules/*.yml
You would then mount a host rules directory into that container path. Keep rule paths and mount paths consistent; a rule file that exists only on the host is invisible to Prometheus until it is mounted.
Fuller Compose stack with cAdvisor
The following is a practical extension of the official three-service pattern. It publishes Prometheus on 9090, cAdvisor on 8080, and Redis on 6379; mounts the Prometheus configuration read-only; and declares service dependencies. The cAdvisor host mounts allow it to inspect the host’s container and kernel information. Container runtimes and operating systems can impose additional requirements, so verify the cAdvisor image’s current runtime guidance before deploying it on a restricted host.
services:
prometheus:
image: prom/prometheus
command:
- --config.file=/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus-data:/prometheus
depends_on:
- cadvisor
cadvisor:
image: gcr.io/cadvisor/cadvisor
ports:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker:/var/lib/docker:ro
depends_on:
- redis
redis:
image: redis
ports:
- "6379:6379"
volumes:
prometheus-data:
depends_on controls startup ordering; it is not a readiness test. Prometheus may start before an exporter is ready and mark that target down temporarily. Once the endpoint responds, the next scrape can succeed.
Redis appears in the official example as an application container alongside cAdvisor. Prometheus does not automatically scrape every service: only targets listed in scrape_configs are collected. If Redis exposes metrics through a separate exporter, add that exporter as its own service and target its service DNS name.
Adding Grafana without changing Prometheus
Grafana is a consumer of Prometheus data, not a replacement for the scraper. Add it as another Compose service, publish the UI port selected by the Grafana image documentation, and configure a Prometheus data source whose server URL is http://prometheus:9090. That URL must use the Compose service name so Grafana reaches Prometheus over the internal network.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteKeep the responsibilities separate:
- Prometheus owns scraping, rule evaluation, and time-series storage.
- Grafana queries Prometheus and renders dashboards.
- Exporters expose metrics; they do not persist Prometheus history.
Pin a Grafana image version that you have validated rather than relying indefinitely on a moving latest tag. The Prometheus service, configuration mount, scrape jobs, and data volume remain unchanged when Grafana is added.
Rank #4
Start, inspect, and operate the stack
- Validate the two files. Confirm that
docker-compose.ymlandprometheus.ymlare in the directory from which you will run Compose, and that the YAML indentation is valid. - Start in the background. Run
docker compose up -d. The current command uses the Compose v2 plugin; older documentation may showdocker-compose up. - Check service state. Run
docker compose ps. Prometheus should have a published 9090 port; the fuller example also publishes 8080 and 6379. - Read startup output. Run
docker compose logs prometheusordocker compose logsfor all services. Configuration parse errors and permission problems normally appear here. - Open the Prometheus interface. Visit
http://localhost:9090on the machine running Docker. - Check target health. In Prometheus, open the targets page. The
prometheusjob should resolve toprometheus:9090; the cAdvisor job should resolve tocadvisor:8080when that service is running. - Check an endpoint directly. Open the relevant service’s
/metricsendpoint. For cAdvisor, that ishttp://localhost:8080/metricswhen port 8080 is published to the host.
Compose also supports stopping the project, rebuilding or pulling changed services, streaming logs, and running one-off commands. Use the project directory and the same Compose file for those operations so you act on the intended stack.
Reload configuration safely
Prometheus can reload a valid configuration without rebuilding the container. Enable its lifecycle endpoint by adding --web.enable-lifecycle to the service command:
command:
- --config.file=/etc/prometheus/prometheus.yml
- --web.enable-lifecycle
After editing the host’s prometheus.yml, request a reload:
curl -X POST http://localhost:9090/-/reload
Prometheus also accepts SIGHUP. If the new YAML is malformed, Prometheus does not apply the change; the previous valid configuration continues running. Check the service logs and fix the syntax before retrying. A reload changes scrape configuration but does not migrate or recreate the persistent data volume.
Compose DNS versus localhost
localhost always means “this container” from a container’s point of view. Therefore, localhost:9090 in the Prometheus container points back to Prometheus itself; it does not point to cAdvisor, Redis, or your host. Use Compose service names for internal traffic:
Best Value
| Caller | Correct destination | Reason |
|---|---|---|
| Prometheus scraping itself | prometheus:9090 |
Prometheus resolves the service name on the Compose network. |
| Prometheus scraping cAdvisor | cadvisor:8080 |
cAdvisor is a separate container and service. |
| Grafana querying Prometheus | http://prometheus:9090 |
Grafana reaches the Prometheus service internally. |
| Your browser on the Docker host | http://localhost:9090 |
The published host port forwards to the Prometheus container. |
Persistence choices and backup implications
| Storage method | How it appears in Compose | When it fits | Operational consideration |
|---|---|---|---|
| Named volume | prometheus-data:/prometheus plus a top-level volumes entry |
Most straightforward single-host deployment | Docker manages the location; include the volume in your backup plan. |
| Bind mount | ./data:/prometheus |
You need an explicit host path or host-level backup policy | The directory must exist and have permissions compatible with the container. |
Changing the storage declaration changes where new writes go; it does not copy existing data automatically. Stop the stack and plan a deliberate data migration before switching from a named volume to a bind mount. Never remove the volume casually: deleting it removes the retained time series.
Minimal versus fuller stack
| Characteristic | Prometheus-only file | Prometheus plus cAdvisor and Redis |
|---|---|---|
| Compose services | One | Three |
| Targets monitored by the supplied configuration | Prometheus itself | Prometheus and cAdvisor; Redis is present but requires an exporter or suitable endpoint before it is monitored |
| Container metrics | Not included | cAdvisor endpoint on port 8080 |
| Persistence | Named volume at /prometheus |
Same Prometheus named volume; cAdvisor and Redis storage are not specified by this example |
| Scrape cadence | 15-second global default | 15-second global default, with cAdvisor at 5 seconds |
| Published ports | 9090 | 9090, 8080, and 6379 |
| Operational complexity | Lowest; useful for validating Prometheus configuration | Higher; adds exporter permissions, dependency ordering, and more exposed endpoints |
There is no universal performance benchmark in the official setup documentation for choosing between these layouts. Select the smallest stack that covers the metrics you actually need, then add services when a concrete monitoring requirement justifies the extra surface area.
Docker daemon metrics are a separate path
Docker’s own metrics endpoint is configured through the daemon’s metrics-addr setting, commonly 127.0.0.1:9323. Those metrics describe Docker itself, not the applications running in its containers. Docker notes that the available metric names are still in active development.
Do not assume that adding cAdvisor or a Redis container automatically enables Docker-daemon metrics. Treat daemon metrics as a separate target and configuration decision. In particular, a daemon bound only to host loopback is not automatically reachable from a Prometheus container through the container’s own localhost.
Troubleshooting checklist
Prometheus exits immediately
- Run
docker compose logs prometheusand look for a YAML parse error or an unreadable configuration path. - Confirm the host file is exactly
./prometheus.ymlrelative to the directory where Compose runs. - Confirm the command path and mount destination both use
/etc/prometheus/prometheus.yml.
The targets page shows “down”
- Check that the exporter service appears in
docker compose ps. - Use the service DNS name and container port, such as
cadvisor:8080, notlocalhost. - Inspect exporter logs and open its published
/metricsendpoint from the Docker host. - Remember that
depends_oncontrols startup order, not application readiness; retry after the service finishes initializing.
Metrics vanished after an update
- Check that the Prometheus service still mounts a named volume or bind mount at
/prometheus. - Verify you did not remove the named volume while cleaning up containers.
- Check that a changed Compose project name did not create a different volume with a similar name.
A configuration reload has no effect
- Ensure
--web.enable-lifecycleis present before using/-/reload. - Read the logs for YAML errors. Prometheus keeps the last valid configuration when the replacement is malformed.
- Confirm that you edited the host file actually mounted into the running container.
Ports cannot be opened
- Another process may already be using 9090, 8080, or 6379. Change the host side of the mapping, for example
19090:9090, while leaving the container target port unchanged. - After changing a port, use the new host port in your browser; internal scrape targets still use service names and container ports.
Production-minded decisions before you expand
- Pin image versions. A moving image tag can change behavior when the stack is recreated. Record the version you validated.
- Expose only required ports. Every published port increases the reachable surface of the host. Keep internal-only services un published when host access is unnecessary.
- Choose intervals deliberately. The 5-second cAdvisor interval is useful for fast-changing container signals but produces more samples than the 15-second default.
- Back up the data path. A Compose file can recreate containers, but it cannot reconstruct deleted time series.
- Test configuration changes. Reload only after validating YAML and watch the logs and targets page for the expected result.
With these pieces in place, the Compose file remains the control plane, prometheus.yml remains the source of scrape and rule definitions, exporters remain independently replaceable services, and the named volume preserves the history that makes monitoring useful.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

