Introduction
Alertmanager is the key component in the Prometheus ecosystem for smart alert management. Unlike a simple alert relay, it deduplicates, groups, and routes notifications to various receivers like Slack, email, or PagerDuty, preventing alert fatigue during incidents. In 2026, with the rise of cloud-native infrastructures, mastering Alertmanager is essential for any beginner DevOps or SRE.
This tutorial guides you step by step through a complete Docker Compose installation, including Prometheus to generate real alerts. You'll learn to configure YAML routes, access the intuitive web interface, and test a simple webhook receiver. By the end, you'll have a production-ready, scalable setup worth bookmarking. Imagine: a high CPU alert triggers a grouped Slack message—that's the real power we're unlocking here.
Prerequisites
- Docker and Docker Compose installed (version 20+ recommended)
- Basic knowledge of YAML and Prometheus (simple concepts explained)
- A terminal (bash/zsh)
- Ports 9090, 9093, and 3000 free on localhost
- Optional: Slack account to test webhooks
Create the project structure
mkdir alertmanager-tutorial
cd alertmanager-tutorial
git init
mkdir -p prometheus/config
mkdir -p alertmanager/config
touch docker-compose.yml
touch prometheus/config/prometheus.yml
touch prometheus/config/rules.yml
touch alertmanager/config/alertmanager.yml
echo "Alertmanager project ready!"This bash script initializes a structured project folder with the necessary directories for Prometheus and Alertmanager. It creates all the empty YAML files ready for configuration. Avoid pitfalls by using absolute paths if you're outside a Git workspace.
Configure Docker Compose
Docker Compose orchestrates Prometheus, Alertmanager, and a metrics exporter (node-exporter) to simulate real data. This avoids complex native installations, making the setup portable and reproducible.
docker-compose.yml file
version: '3.8'
services:
prometheus:
image: prom/prometheus:v2.54.0
volumes:
- ./prometheus/config:/etc/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
ports:
- "9090:9090"
restart: always
alertmanager:
image: prom/alertmanager:v0.27.0
volumes:
- ./alertmanager/config:/etc/alertmanager
command:
- '--config.file=/etc/alertmanager/alertmanager.yml'
- '--storage.path=/alertmanager'
ports:
- "9093:9093"
restart: always
node_exporter:
image: prom/node-exporter:v1.8.2
ports:
- "9100:9100"
restart: alwaysThis docker-compose.yml launches three services: Prometheus (port 9090), Alertmanager (9093), and node-exporter for CPU/memory metrics. Volumes mount your custom YAML configs. Common pitfall: forget quotes on long commands, causing parse errors.
Basic Prometheus configuration
global:
scrape_interval: 15s
rule_files:
- "rules.yml"
alerting:
alertmanagers:
- static_configs:
- targets:
- alertmanager:9093
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node'
static_configs:
- targets: ['node_exporter:9100']Prometheus scrapes metrics every 15s and forwards alerts to Alertmanager on internal port 9093. The alerting section is crucial: without it, no routing happens. Always verify targets to avoid connection refusals in clusters.
Start the services
Now run docker compose up -d in the project folder. Check logs with docker compose logs -f. Access Prometheus at http://localhost:9090 and Alertmanager at http://localhost:9093. Alertmanager's UI already shows silences and configs in real time.
High CPU alert rule
groups:
- name: example
rules:
- alert: HighCPUUsage
expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 1m
labels:
severity: warning
annotations:
summary: "High CPU usage on {{ $labels.instance }}"
description: "CPU > 80% for more than 1 minute."This rule triggers an alert if CPU exceeds 80% for 1 minute, with labels and annotations for routing. Reload Prometheus via the UI (Status > Rules) after changes. Analogy: like a guard waiting for confirmation before calling reinforcements.
Basic Alertmanager configuration
global:
smtp_smarthost: 'localhost:1025'
smtp_from: 'alertmanager@example.com'
route:
group_by: ['alertname', 'cluster']
group_wait: 30s
group_interval: 5m
repeat_interval: 1h
receiver: 'default'
receivers:
- name: 'default'
webhook_configs:
- url: 'http://httpbin.org/post'
inhibit_rules:
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['alertname', 'cluster', 'service']Alertmanager groups alerts by name and cluster, waits 30s before sending, and routes to a test webhook (httpbin). Inhibitions prevent duplicates. Restart the container after edits: docker compose restart alertmanager. Pitfall: strict YAML indentation!
Test the alert
Generate high CPU: docker run --rm -it --cpus=0.8 ubuntu:22.04 stress --cpu 8 --timeout 300s in the background. Monitor Prometheus > Graph > CPU query, then Alertmanager UI > Alerts. You'll see the grouped alert!
Add a Slack receiver
route:
receiver: slack
group_by: ['alertname']
receivers:
- name: slack
slack_configs:
- api_url: 'https://hooks.slack.com/services/VOTRE/WEBHOOK'
channel: '#alerts'
text: "{{ range .Alerts }}[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .AnnotatedInstance }} {{ .Annotations.summary }}{{ end }}"
send_resolved: trueReplace alertmanager.yml with this snippet for Slack (get api_url from Slack App). It formats messages with status and summary. Tested: resolved alerts are sent too. In production, use Docker secrets for integration.
Best practices
- Strategic group_by: Group by cluster/service to reduce noise (avoid 'instance' alone).
- Progressive repeat_interval: 1h for warnings, 5min for critical—tailor to SLAs.
- Use the UI for silences: Silence manually via localhost:9093/#/silences instead of static configs.
- Monitor Alertmanager: Add it to Prometheus with scrape_config job_name: 'alertmanager'.
- HA setup: Scale with multiple replicas and Consul for discovery in production.
Common errors to avoid
- Misindented YAML: Alertmanager won't start—validate with
yamllintor your IDE. - Port conflicts: Check
netstat -tuln | grep 9093before starting. - No rules_files: Silent alerts—reload Prometheus UI after edits.
- Wrong targets: In Docker, use service names (alertmanager:9093), not localhost.
Next steps
- Official docs: Prometheus Alertmanager
- Advanced: Integrate Grafana for alert dashboards.
- Expert training: Check our Learni monitoring courses for Kubernetes + Prometheus in production.
- GitHub repo example: Fork this tutorial for your labs.