Prometheus is an open source systems monitoring and alerting toolkit. It was originally built at SoundCloud and is now a standalone project maintained by the community. Prometheus collects and stores metrics as time series data: each sample is stored with a timestamp and optional labels (key-value pairs), so you can track how metrics change over time and slice them by job, instance, or other dimensions.
Metrics help you understand how your systems and applications behave. For example, if a web app becomes slow, request rate or latency metrics can show whether the cause is high traffic, slow dependencies, or resource saturation. Prometheus is widely used for monitoring servers, containers, and applications in DevOps and cloud-native environments.
In this guide you will learn how to run Prometheus with Docker and Docker Compose by:
- Confirming Docker and Docker Compose are available
- Creating a minimal Prometheus configuration and running Prometheus in a container
- Using bind mounts or a custom image to supply configuration
- Defining a Compose stack with optional data persistence
- Verifying the setup in the Prometheus UI
By the end, you will have Prometheus running in Docker and ready to scrape targets or extend with Alertmanager and Grafana.
What is Prometheus?
Prometheus scrapes metrics over HTTP from configured targets (such as itself, Node Exporter, or application exporters), stores them in a time-series database, and lets you query them with PromQL (Prometheus Query Language). It can evaluate alerting rules and send notifications to Alertmanager. The official Prometheus documentation describes the architecture and components in detail.
Running Prometheus in Docker or Docker Compose is useful for local development, testing, or small deployments where you prefer containers over a host install. For production at scale, you may later consider Kubernetes; see the Production-Ready Prometheus on Kubernetes guide for a full stack with authentication and high availability.
Prerequisites
Before you start, ensure you have:
- Docker Engine installed and running. On Ubuntu, see How to Install and Use Docker in Ubuntu 22.04; for other distributions, use the official Docker install guide.
- Docker Compose available. Modern Docker Desktop and recent Docker Engine installs include the Compose V2 plugin, so you run
docker compose(with a space). If you use the standalone Python-baseddocker-compose, rundocker-compose(with a hyphen). The examples below usedocker compose; substitutedocker-composeif that is what you have. - Port 9090 free for the Prometheus UI and API (or change the published port in the examples).
Confirm that Docker is working:
| |
You should see both Client and Server sections. Then confirm Compose:
| |
If that fails, try docker-compose version. If neither works, install the Compose plugin or the standalone Compose for your platform.
Prometheus Configuration Overview
Prometheus is configured via a single YAML file. The main parts are:
- global – Default scrape interval and evaluation interval.
- alerting – Optional Alertmanager endpoints for alerts.
- rule_files – Optional files containing recording and alerting rules.
- scrape_configs – List of jobs and targets to scrape (e.g. Prometheus itself, Node Exporter, application metrics).
The minimal config below scrapes only Prometheus itself. You can add more jobs later (e.g. Node Exporter for host metrics).
Running Prometheus with Docker
Official Prometheus images are published on Quay and Docker Hub. A quick start without a custom config is:
| |
That runs Prometheus with its default configuration and exposes the UI on port 9090. For a config you can edit on the host, use a bind mount or a custom image.
Minimal Configuration File
Save the following as prometheus.yml in a directory you will use for config (e.g. ./prometheus):
| |
The prometheus job scrapes the Prometheus server’s own /metrics endpoint. When you add more services (e.g. Node Exporter), add another job with the appropriate targets.
Option 1: Bind-Mount Configuration
Bind-mount your prometheus.yml into the container so you can change it without rebuilding:
| |
Or mount the whole config directory:
| |
Prometheus stores time-series data inside the container by default. For production, use a named volume for data so it survives container removal and upgrades (see Docker volumes and the Compose example below). Reload config at runtime with a SIGHUP or by restarting the container after editing the file.
Option 2: Custom Image
You can bake the config into an image so you do not need a file on the host. Create a directory with prometheus.yml and a Dockerfile:
Dockerfile:
| |
Build and run:
| |
This works well when the config is static and the same across environments. For dynamic or environment-specific config, bind mounts or templating are usually better.
For more options (e.g. dynamic config), see the official Prometheus installation docs (volumes and bind mount, custom image).
Running Prometheus with Docker Compose
Docker Compose lets you define Prometheus (and optionally other services) in a YAML file and start them with one command. Use a bind-mounted config and a named volume for data so metrics persist across restarts and upgrades.
Directory Layout
Create a project directory and put your config there:
| |
prometheus.yml can be the minimal config shown earlier.
Compose File
docker-compose.yaml:
| |
- prometheus.yml is mounted read-only so Prometheus can read it.
- prometheus_data is a named volume so TSDB data persists. Without it, data is lost when the container is removed.
- –web.enable-lifecycle allows reloading config via HTTP (e.g.
curl -X POST http://localhost:9090/-/reload) when using a bind-mounted config.
Start the stack:
| |
Example output:
| |
Check that the container is running:
| |
You should see the prometheus service with port 9090 mapped. Open http://localhost:9090 (or http://your-server:9090) in a browser.
Optional: Add Node Exporter for Host Metrics
To scrape host metrics (CPU, memory, disk) from the same host where Docker runs, you can add Node Exporter as a sidecar and point Prometheus at it. Add a service and a scrape job.
docker-compose.yaml (excerpt; add the node_exporter service and update prometheus command so it can reach it):
| |
On Linux, use extra_hosts: - "host.docker.internal:host-gateway" so Prometheus (in Docker) can reach Node Exporter on the host. Then in prometheus.yml, add a job:
| |
Restart: docker compose up -d. After a scrape, you will see the node job in the Prometheus UI. For a full Linux + Prometheus + Grafana setup, see Monitor Linux Server With Prometheus and Grafana.
Verifying the Setup
Open the Prometheus UI Go to http://localhost:9090 (or http://your-server:9090). You should see the Prometheus interface.
Check targets Go to Status → Targets. The
prometheusjob should be UP. If you added Node Exporter, thenodejob should be UP after the first scrape.Run a query Go to Graph (or the query tab), enter
upand click Execute. You should see at least one series withjob="prometheus"andup=1.Reload config (if using bind mount) After editing
prometheus.yml, either restart the container or, if you started with--web.enable-lifecycle, run:1curl -X POST http://localhost:9090/-/reload
Troubleshooting
Container exits immediately Check logs:
docker compose logs prometheusordocker logs prometheus. Often the cause is an invalid or missing config file. Ensure the path in the volume mount is correct and the YAML is valid.Target is DOWN If the target is another container, ensure they are on the same Docker network and use the service name (e.g.
node_exporter:9100). If the target is on the host, usehost.docker.internal:9100(withhost-gateway) or the host’s IP.No data in Graph Confirm the scrape interval has passed (default 15s). Check Status → Targets and fix any DOWN targets. Ensure the configured port (e.g. 9090 for Prometheus) is correct.
Permission denied on volume Prometheus runs as a non-root user. If you use a bind mount for the data directory, ensure the directory is writable by the Prometheus user (UID in the image) or use a named volume instead.
Summary
You now have Prometheus running with Docker or Docker Compose:
- Docker: Use
docker runwith a bind-mountedprometheus.ymlor a custom image. Add a named volume for production data. - Docker Compose: Define the service with a bind-mounted config and a named volume for
/prometheus; usedocker compose up -dto run. - Verification: Open the UI, check Status → Targets, and run a query such as
up.
From here you can add more scrape jobs (Node Exporter, application exporters), configure Alertmanager, or connect Grafana to Prometheus for dashboards. For installing and configuring Prometheus on a bare Linux server, see How to Install and Configure Prometheus on a Linux Server; for Kubernetes, see Production-Ready Prometheus on Kubernetes.
Related Posts
- Monitor Linux Server With Prometheus and Grafana – Node Exporter, Prometheus, and Grafana on a Linux host
- How to Install and Configure Prometheus on a Linux Server – Host-based Prometheus installation
- Production-Ready Prometheus on Kubernetes – Prometheus on Kubernetes with auth and HA
- How to Install and Configure Prometheus Alertmanager in Linux – Alerting with Alertmanager
- How to Run Grafana Loki with Docker and Docker Compose – Logs with Loki in Docker
- How to Run Grafana OSS in Docker and Docker Compose – Grafana in Docker