Cloud Security
RAMESH
0 followers
Monitoring containers is an important part of running reliable Docker-based applications. Simply knowing that a container is running is not enough—we also need to understand how much CPU, memory, disk, and other system resources it is consuming.
In this guide, we will build a simple Docker monitoring stack using Prometheus, cAdvisor, Node Exporter, and Grafana.
By the end, you will have a monitoring setup where:
cAdvisor collects Docker container metrics. Node Exporter collects host-system metrics. Prometheus collects and stores those metrics. Grafana turns the collected metrics into dashboards and visualizations.
The monitoring setup can be understood as:
┌─────────────────┐
│ Docker Host │
│ │
│ Containers │
└────────┬────────┘
│
┌──────────┴──────────┐
│ │
┌──────▼──────┐ ┌──────▼────────┐
│ cAdvisor │ │ Node Exporter │
│ Container │ │ Host Metrics │
│ Metrics │ │ │
└──────┬──────┘ └──────┬────────┘
│ │
└──────────┬──────────┘
│
┌──────▼──────┐
│ Prometheus │
│ Metrics │
│ Storage │
└──────┬──────┘
│
┌──────▼──────┐
│ Grafana │
│ Dashboards │
└─────────────┘Before starting, make sure Docker and Docker Compose are installed on your system.
You should be comfortable with basic Docker commands and YAML configuration files.
Create a docker-compose.yml file:
nano docker-compose.ymlAdd the following configuration:
version: "3"
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
ports:
- 9090:9090
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--storage.tsdb.path=/prometheus"
- "--web.console.libraries=/usr/share/prometheus/console_libraries"
- "--web.console.templates=/usr/share/prometheus/consoles"
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: cadvisor
ports:
- 8080:8080
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
node-exporter:
image: prom/node-exporter:latest
container_name: node-exporter
ports:
- 9100:9100
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- "--path.procfs=/host/proc"
- "--path.sysfs=/host/sys"
- '--collector.filesystem.ignored-mount-points="^/(sys|proc|dev|host|etc)($$|/)"'
volumes:
prometheus_data:Prometheus is responsible for collecting and storing metrics. In this setup, it listens on port 9090.
The configuration file is mounted into the container:
- ./prometheus.yml:/etc/prometheus/prometheus.ymlA persistent volume is also used so that Prometheus data can survive container restarts.
cAdvisor provides container-level metrics. It can monitor Docker containers and expose information about their resource usage.
It is exposed on:
http://localhost:8080Node Exporter exposes metrics about the underlying host system.
It runs on port:
9100The configuration mounts /proc, /sys, and the host filesystem into the container so that Node Exporter can access the required host information.
Create the Prometheus configuration:
nano prometheus.ymlAdd:
global:
scrape_interval: 15s
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]
- job_name: "cadvisor"
static_configs:
- targets: ["cadvisor:8080"]
- job_name: "node-exporter"
static_configs:
- targets: ["node-exporter:9100"]The scrape_interval determines how frequently Prometheus collects metrics. Here, Prometheus attempts to scrape the configured targets every 15 seconds.
The important part is the target configuration:
targets: ["cadvisor:8080"]and:
targets: ["node-exporter:9100"]Because these services are running within the same Docker Compose network, their service names can be used for communication.
Start the services using Docker Compose:
docker-compose up -dYou can check whether the containers are running with:
docker psYou should see containers for:
prometheus
cadvisor
node-exporterAt this point, the basic monitoring stack is running.
Now we need Grafana to visualize the metrics collected by Prometheus.
Add the following service to docker-compose.yml:
grafana:
image: grafana/grafana:latest
container_name: grafana
ports:
- 3000:3000
volumes:
- grafana_data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=adminAlso add the Grafana volume:
volumes:
grafana_data: {}
prometheus_data: {}Your monitoring stack now contains four major components:
Prometheus
cAdvisor
Node Exporter
GrafanaRestart or recreate the services:
docker-compose up -dCheck the containers again:
docker psGrafana is available at:
http://localhost:3000Open the address in your browser.
The Grafana service in this setup uses:
Username: admin
Password: adminFor a real deployment, you should change the default credentials rather than using them in production.
Once you are inside Grafana, add Prometheus as a data source.
Navigate to:
Configuration → Data SourcesCreate a new Prometheus data source.
For the Prometheus URL, use:
http://prometheus:9090The important detail here is that Grafana is communicating with Prometheus through the Docker Compose network.
Using:
http://prometheus:9090allows Grafana to reach the Prometheus container using its Compose service name.
After entering the URL, save and test the data source.
Instead of creating every visualization manually, Grafana allows dashboards to be imported using dashboard IDs.
In this setup, dashboard ID:
16310can be imported into Grafana.
Go to:
Dashboards → ImportEnter:
16310and proceed with the import.
Once the dashboard is connected to the Prometheus data source, Grafana can display the collected monitoring information.
At this point, it is useful to understand what happens when the system is running.
Suppose a Docker container starts consuming more CPU.
The flow is approximately:
Docker Container
↓
cAdvisor
↓
Prometheus
↓
Grafana
↓
VisualizationSimilarly, host-level information is exposed by Node Exporter:
Docker Host
↓
Node Exporter
↓
Prometheus
↓
GrafanaPrometheus periodically scrapes the configured endpoints and stores the resulting time-series data.
Grafana then queries Prometheus and presents that data through dashboards.
Prometheus and Grafana solve different parts of the monitoring problem.
Prometheus focuses on:
Collecting metrics Scraping monitoring endpoints Storing time-series data Querying metrics
Grafana focuses primarily on:
Visualization Dashboards Graphs Monitoring panels Presenting metrics in an easier-to-understand format
This separation makes the stack flexible. Prometheus handles the metric collection and storage while Grafana provides the visualization layer.
These two exporters provide different perspectives.
cAdvisor focuses on containers and exposes container-related resource metrics.
Node Exporter focuses on the host machine and exposes system-level metrics.
Using both allows us to observe the relationship between the host and the containers running on it.
For example:
Host CPU / Memory
│
│
▼
Node Exporter
│
▼
Prometheus
│
▼
Grafana
Container CPU / Memory
│
│
▼
cAdvisor
│
▼
Prometheus
│
▼
GrafanaHere are some commands that are useful while working with this monitoring stack.
Check running containers:
docker psView logs from Prometheus:
docker logs prometheusView cAdvisor logs:
docker logs cadvisorView Node Exporter logs:
docker logs node-exporterView Grafana logs:
docker logs grafanaStop the stack:
docker-compose downStart it again:
docker-compose up -dThe services in this setup use the following ports:
| Service | Port | Purpose |
|---|---|---|
| Prometheus | 9090 | Metrics collection and Prometheus UI |
| cAdvisor | 8080 | Container metrics |
| Node Exporter | 9100 | Host metrics |
| Grafana | 3000 | Monitoring dashboards |
You can access the services locally using:
Prometheus → http://localhost:9090
cAdvisor → http://localhost:8080
Node Exporter → http://localhost:9100
Grafana → http://localhost:3000In this project, we created a Docker-based monitoring stack using Prometheus, cAdvisor, Node Exporter, and Grafana.
The overall workflow is:
Docker Containers ──→ cAdvisor ──┐
│
Docker Host ────────→ Node Exporter
│
▼
Prometheus
│
▼
Grafana
│
▼
DashboardsThis setup provides a foundation for monitoring Docker environments and understanding how applications and infrastructure consume resources.
Once the basic stack is working, it can be extended with alerting, additional exporters, custom Prometheus queries, and more specialized Grafana dashboards.
The key takeaway is that monitoring becomes much more useful when raw metrics are transformed into something that can be observed and analyzed easily. Prometheus provides the metrics layer, while Grafana turns those metrics into a practical visualization interface.
