Deploy a complete monitoring solution using Prometheus for metrics collection and Grafana for visualization with Docker Compose. This setup provides comprehensive system monitoring, alerting capabilities, and customizable dashboards.
Prerequisites
- Docker and Docker Compose installed
- At least 4GB RAM available
- Ports 3000, 8080, 9090, 9093, 9100 available
What this solves
A Prometheus and Grafana monitoring stack gives you complete visibility into your infrastructure and applications. Prometheus collects and stores metrics while Grafana provides powerful visualization dashboards and alerting capabilities. This Docker Compose setup simplifies deployment and makes the entire stack portable across environments.
Step-by-step installation
Install Docker and Docker Compose
First, install Docker and Docker Compose on your system. These tools will manage our monitoring containers.
sudo apt update
sudo apt install -y docker.io docker-compose-plugin
sudo systemctl enable --now docker
sudo usermod -aG docker $USER
Log out and back in for the group membership to take effect, or run:
newgrp docker
Create project directory structure
Create a dedicated directory for your monitoring stack with subdirectories for configuration files and data persistence.
mkdir -p monitoring-stack/{prometheus,grafana/provisioning/{datasources,dashboards}}
cd monitoring-stack
Configure Prometheus
Create the main Prometheus configuration file that defines scrape targets and retention policies.
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- "alert_rules.yml"
alerting:
alertmanagers:
- static_configs:
- targets:
- alertmanager:9093
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node-exporter'
static_configs:
- targets: ['node-exporter:9100']
- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']
- job_name: 'grafana'
static_configs:
- targets: ['grafana:3000']
Create Prometheus alert rules
Define alert conditions for common monitoring scenarios like high CPU usage and service downtime.
groups:
- name: system_alerts
rules:
- alert: HighCPUUsage
expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 5m
labels:
severity: warning
annotations:
summary: "High CPU usage detected on {{ $labels.instance }}"
description: "CPU usage is above 80% for more than 5 minutes on {{ $labels.instance }}"
- alert: HighMemoryUsage
expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 85
for: 5m
labels:
severity: warning
annotations:
summary: "High memory usage detected on {{ $labels.instance }}"
description: "Memory usage is above 85% for more than 5 minutes on {{ $labels.instance }}"
- alert: ServiceDown
expr: up == 0
for: 2m
labels:
severity: critical
annotations:
summary: "Service {{ $labels.job }} is down"
description: "Service {{ $labels.job }} on {{ $labels.instance }} has been down for more than 2 minutes"
Configure Grafana datasource
Set up Prometheus as a datasource for Grafana with automatic provisioning.
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
isDefault: true
editable: true
Configure Grafana dashboard provisioning
Enable automatic dashboard loading from the dashboards directory.
apiVersion: 1
providers:
- name: 'default'
orgId: 1
folder: ''
folderUid: ''
type: file
disableDeletion: false
editable: true
updateIntervalSeconds: 10
allowUiUpdates: true
options:
path: /etc/grafana/provisioning/dashboards
Create Alertmanager configuration
Configure Alertmanager to handle alert routing and notifications via email and Slack.
global:
smtp_smarthost: 'localhost:587'
smtp_from: 'alerts@example.com'
route:
group_by: ['alertname']
group_wait: 10s
group_interval: 10s
repeat_interval: 1h
receiver: 'web.hook'
receivers:
- name: 'web.hook'
email_configs:
- to: 'admin@example.com'
subject: '[ALERT] {{ range .Alerts }}{{ .Annotations.summary }}{{ end }}'
body: |
{{ range .Alerts }}
Alert: {{ .Annotations.summary }}
Description: {{ .Annotations.description }}
Instance: {{ .Labels.instance }}
Severity: {{ .Labels.severity }}
{{ end }}
inhibit_rules:
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['alertname', 'dev', 'instance']
Create Docker Compose configuration
Define all services including Prometheus, Grafana, Alertmanager, and system monitoring exporters.
version: '3.8'
services:
prometheus:
image: prom/prometheus:v2.47.2
container_name: 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'
- '--storage.tsdb.retention.time=200h'
- '--web.enable-lifecycle'
restart: unless-stopped
ports:
- "9090:9090"
volumes:
- ./prometheus:/etc/prometheus
- prometheus_data:/prometheus
networks:
- monitoring
alertmanager:
image: prom/alertmanager:v0.26.0
container_name: alertmanager
restart: unless-stopped
ports:
- "9093:9093"
volumes:
- ./alertmanager:/etc/alertmanager
command:
- '--config.file=/etc/alertmanager/alertmanager.yml'
- '--storage.path=/alertmanager'
- '--web.external-url=http://localhost:9093'
networks:
- monitoring
grafana:
image: grafana/grafana:10.2.0
container_name: grafana
restart: unless-stopped
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin123
- GF_USERS_ALLOW_SIGN_UP=false
volumes:
- grafana_data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning
networks:
- monitoring
node-exporter:
image: prom/node-exporter:v1.6.1
container_name: node-exporter
restart: unless-stopped
ports:
- "9100:9100"
command:
- '--path.procfs=/host/proc'
- '--path.rootfs=/rootfs'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
networks:
- monitoring
cadvisor:
image: gcr.io/cadvisor/cadvisor:v0.47.2
container_name: cadvisor
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker:/var/lib/docker:ro
- /dev/disk:/dev/disk:ro
devices:
- /dev/kmsg:/dev/kmsg
networks:
- monitoring
volumes:
prometheus_data:
grafana_data:
networks:
monitoring:
driver: bridge
Set proper permissions
Ensure the monitoring containers can read configuration files and write data to mounted volumes.
sudo chown -R 472:472 grafana/
sudo chmod -R 755 prometheus/ alertmanager/
Start the monitoring stack
Launch all monitoring services with Docker Compose and verify they start successfully.
docker compose up -d
docker compose ps
Configure basic system dashboard
Create a comprehensive system monitoring dashboard for immediate insights into server performance.
{
"dashboard": {
"id": null,
"title": "System Overview",
"tags": ["system", "monitoring"],
"style": "dark",
"timezone": "browser",
"panels": [
{
"id": 1,
"title": "CPU Usage",
"type": "stat",
"targets": [
{
"expr": "100 - (avg by (instance) (rate(node_cpu_seconds_total{mode=\"idle\"}[5m])) * 100)",
"refId": "A"
}
],
"fieldConfig": {
"defaults": {
"unit": "percent",
"min": 0,
"max": 100
}
},
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 0}
},
{
"id": 2,
"title": "Memory Usage",
"type": "stat",
"targets": [
{
"expr": "(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100",
"refId": "A"
}
],
"fieldConfig": {
"defaults": {
"unit": "percent",
"min": 0,
"max": 100
}
},
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 0}
}
],
"time": {
"from": "now-6h",
"to": "now"
},
"refresh": "30s"
}
}
Configure alerting and notifications
Set up email notifications
Configure SMTP settings in the Alertmanager configuration for email alerts. Update the alertmanager.yml file with your email server details.
global:
smtp_smarthost: 'smtp.gmail.com:587'
smtp_from: 'monitoring@example.com'
smtp_auth_username: 'monitoring@example.com'
smtp_auth_password: 'your-app-password'
route:
group_by: ['alertname', 'cluster', 'service']
group_wait: 10s
group_interval: 10s
repeat_interval: 12h
receiver: 'email-notifications'
routes:
- match:
severity: critical
receiver: 'critical-alerts'
group_wait: 5s
repeat_interval: 5m
receivers:
- name: 'email-notifications'
email_configs:
- to: 'admin@example.com'
subject: '[{{ .Status | toUpper }}] {{ .GroupLabels.alertname }}'
html: |
Alert Details
{{ range .Alerts }}
Alert: {{ .Annotations.summary }}
Description: {{ .Annotations.description }}
Instance: {{ .Labels.instance }}
Severity: {{ .Labels.severity }}
Started: {{ .StartsAt.Format "2006-01-02 15:04:05" }}
{{ end }}
- name: 'critical-alerts'
email_configs:
- to: 'oncall@example.com'
subject: '[CRITICAL] {{ .GroupLabels.alertname }}'
html: |
CRITICAL ALERT
{{ range .Alerts }}
{{ .Annotations.summary }}
{{ .Annotations.description }}
Instance: {{ .Labels.instance }}
Started: {{ .StartsAt.Format "2006-01-02 15:04:05" }}
{{ end }}
Configure Slack notifications
Add Slack webhook integration to receive alerts in your team channels.
cat >> alertmanager/alertmanager.yml << 'EOF'
- name: 'slack-notifications'
slack_configs:
- api_url: 'https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK'
channel: '#alerts'
username: 'Alertmanager'
title: '{{ range .Alerts }}{{ .Annotations.summary }}{{ end }}'
text: |
{{ range .Alerts }}
Alert: {{ .Annotations.summary }}
Description: {{ .Annotations.description }}
Instance: {{ .Labels.instance }}
Severity: {{ .Labels.severity }}
{{ end }}
EOF
Set up Grafana alerting
Configure Grafana's unified alerting system for dashboard-based alerts with multiple notification channels.
docker exec -it grafana grafana-cli admin reset-admin-password newpassword123
Access Grafana at http://your-server-ip:3000 and configure notification policies under Alerting → Notification policies.
Test alerting system
Trigger a test alert to verify your notification channels are working correctly.
# Stop node-exporter to trigger a service down alert
docker compose stop node-exporter
Check alert status in Prometheus
curl -s http://localhost:9090/api/v1/alerts | jq '.data.alerts[] | select(.labels.alertname=="ServiceDown")'
Restart the service
docker compose start node-exporter
Set up Grafana dashboards
Import community dashboards
Download popular community dashboards for comprehensive system monitoring.
# Download Node Exporter Full dashboard
curl -s https://grafana.com/api/dashboards/1860/revisions/37/download | jq '.dashboard' > grafana/provisioning/dashboards/node-exporter-full.json
Download Docker container dashboard
curl -s https://grafana.com/api/dashboards/193/revisions/2/download | jq '.dashboard' > grafana/provisioning/dashboards/docker-containers.json
Create custom application dashboard
Build a custom dashboard for monitoring your specific applications and services.
{
"dashboard": {
"id": null,
"title": "Application Metrics",
"tags": ["application", "custom"],
"style": "dark",
"timezone": "browser",
"panels": [
{
"id": 1,
"title": "HTTP Request Rate",
"type": "graph",
"targets": [
{
"expr": "rate(http_requests_total[5m])",
"refId": "A",
"legendFormat": "{{ method }} {{ status_code }}"
}
],
"yAxes": [
{
"label": "Requests/sec",
"min": 0
}
],
"gridPos": {"h": 9, "w": 12, "x": 0, "y": 0}
},
{
"id": 2,
"title": "Response Time",
"type": "graph",
"targets": [
{
"expr": "histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))",
"refId": "A",
"legendFormat": "95th percentile"
},
{
"expr": "histogram_quantile(0.50, rate(http_request_duration_seconds_bucket[5m]))",
"refId": "B",
"legendFormat": "50th percentile"
}
],
"yAxes": [
{
"label": "Duration (seconds)",
"min": 0
}
],
"gridPos": {"h": 9, "w": 12, "x": 12, "y": 0}
}
],
"time": {
"from": "now-1h",
"to": "now"
},
"refresh": "10s"
}
}
Configure dashboard permissions
Set up role-based access control for dashboards to control who can view and edit monitoring data.
# Restart Grafana to load new dashboards
docker compose restart grafana
Wait for Grafana to start
sleep 30
Verify dashboards loaded
curl -s -u admin:admin123 http://localhost:3000/api/search | jq '.[].title'
Verify your setup
Check that all monitoring components are running and accessible.
# Check all services are running
docker compose ps
Verify Prometheus is collecting metrics
curl -s http://localhost:9090/api/v1/targets | jq '.data.activeTargets[] | {job: .labels.job, health: .health}'
Test Grafana API
curl -s -u admin:admin123 http://localhost:3000/api/health
Check Alertmanager status
curl -s http://localhost:9093/-/healthy
Verify node metrics are available
curl -s http://localhost:9100/metrics | grep node_cpu_seconds_total | head -5
Access the web interfaces:
- Grafana:
http://your-server-ip:3000(admin/admin123) - Prometheus:
http://your-server-ip:9090 - Alertmanager:
http://your-server-ip:9093 - Node Exporter metrics:
http://your-server-ip:9100/metrics
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Grafana shows "No data" for dashboards | Prometheus datasource not configured | Check datasource URL in grafana/provisioning/datasources/prometheus.yml |
| Permission denied on Grafana volumes | Incorrect file ownership | sudo chown -R 472:472 grafana/ and restart containers |
| Node exporter metrics missing | Host paths not mounted correctly | Verify volume mounts in docker-compose.yml match your system |
| Alerts not firing | Alert rules syntax error | Check Prometheus logs: docker logs prometheus |
| Email notifications not working | SMTP configuration incorrect | Test SMTP settings and check Alertmanager logs |
| High memory usage by Prometheus | Too many metrics or long retention | Adjust retention time or increase memory limits |
Next steps
- Configure Prometheus Alertmanager with email notifications for production monitoring
- Set up NGINX monitoring with Prometheus and Grafana for web server observability
- Monitor Docker containers with Prometheus and Grafana using cAdvisor for comprehensive metrics collection
- Configure Grafana LDAP authentication and role-based access control with Active Directory integration
- Set up Prometheus Blackbox Exporter for uptime monitoring with SSL and alerting
Running this in production?
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Default configuration
INSTALL_DIR="/opt/monitoring-stack"
DOCKER_USER=${SUDO_USER:-$USER}
# Usage message
usage() {
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " -d, --dir DIR Installation directory (default: /opt/monitoring-stack)"
echo " -h, --help Show this help message"
exit 1
}
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
-d|--dir)
INSTALL_DIR="$2"
shift 2
;;
-h|--help)
usage
;;
*)
echo -e "${RED}Error: Unknown option $1${NC}"
usage
;;
esac
done
# Error handler for cleanup
cleanup() {
echo -e "${RED}Error occurred. Cleaning up...${NC}"
if [[ -d "$INSTALL_DIR" ]]; then
rm -rf "$INSTALL_DIR"
fi
}
trap cleanup ERR
# Check if running as root or with sudo
if [[ $EUID -ne 0 ]]; then
echo -e "${RED}Error: This script must be run as root or with sudo${NC}"
exit 1
fi
echo -e "${GREEN}Starting Prometheus and Grafana monitoring stack installation${NC}"
# Detect distribution
echo -e "${YELLOW}[1/8] Detecting distribution...${NC}"
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_UPDATE="apt update"
PKG_INSTALL="apt install -y"
DOCKER_COMPOSE_PKG="docker-compose-plugin"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
DOCKER_COMPOSE_PKG="docker-compose-plugin"
;;
amzn)
PKG_MGR="yum"
PKG_UPDATE="yum update -y"
PKG_INSTALL="yum install -y"
DOCKER_COMPOSE_PKG="docker-compose"
;;
*)
echo -e "${RED}Error: Unsupported distribution: $ID${NC}"
exit 1
;;
esac
echo -e "${GREEN}Detected: $PRETTY_NAME${NC}"
else
echo -e "${RED}Error: Cannot detect distribution${NC}"
exit 1
fi
# Install Docker and Docker Compose
echo -e "${YELLOW}[2/8] Installing Docker and Docker Compose...${NC}"
$PKG_UPDATE
$PKG_INSTALL docker.io $DOCKER_COMPOSE_PKG
# Start and enable Docker
systemctl enable --now docker
usermod -aG docker $DOCKER_USER
# Create project directory structure
echo -e "${YELLOW}[3/8] Creating directory structure...${NC}"
mkdir -p "$INSTALL_DIR"/{prometheus,grafana/provisioning/{datasources,dashboards},alertmanager}
chown -R $DOCKER_USER:$DOCKER_USER "$INSTALL_DIR"
chmod -R 755 "$INSTALL_DIR"
# Create Prometheus configuration
echo -e "${YELLOW}[4/8] Creating Prometheus configuration...${NC}"
cat > "$INSTALL_DIR/prometheus/prometheus.yml" << 'EOF'
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- "alert_rules.yml"
alerting:
alertmanagers:
- static_configs:
- targets:
- alertmanager:9093
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node-exporter'
static_configs:
- targets: ['node-exporter:9100']
- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']
- job_name: 'grafana'
static_configs:
- targets: ['grafana:3000']
EOF
# Create Prometheus alert rules
cat > "$INSTALL_DIR/prometheus/alert_rules.yml" << 'EOF'
groups:
- name: system_alerts
rules:
- alert: HighCPUUsage
expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 5m
labels:
severity: warning
annotations:
summary: "High CPU usage detected on {{ $labels.instance }}"
description: "CPU usage is above 80% for more than 5 minutes on {{ $labels.instance }}"
- alert: HighMemoryUsage
expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 85
for: 5m
labels:
severity: warning
annotations:
summary: "High memory usage detected on {{ $labels.instance }}"
description: "Memory usage is above 85% for more than 5 minutes on {{ $labels.instance }}"
- alert: ServiceDown
expr: up == 0
for: 2m
labels:
severity: critical
annotations:
summary: "Service {{ $labels.job }} is down"
description: "Service {{ $labels.job }} on {{ $labels.instance }} has been down for more than 2 minutes"
EOF
# Create Grafana datasource configuration
echo -e "${YELLOW}[5/8] Creating Grafana configuration...${NC}"
cat > "$INSTALL_DIR/grafana/provisioning/datasources/prometheus.yml" << 'EOF'
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
isDefault: true
editable: true
EOF
# Create Grafana dashboard provisioning
cat > "$INSTALL_DIR/grafana/provisioning/dashboards/dashboard.yml" << 'EOF'
apiVersion: 1
providers:
- name: 'default'
orgId: 1
folder: ''
folderUid: ''
type: file
disableDeletion: false
editable: true
updateIntervalSeconds: 10
allowUiUpdates: true
options:
path: /etc/grafana/provisioning/dashboards
EOF
# Create Alertmanager configuration
cat > "$INSTALL_DIR/alertmanager/alertmanager.yml" << 'EOF'
global:
smtp_smarthost: 'localhost:587'
smtp_from: 'alerts@example.com'
route:
group_by: ['alertname']
group_wait: 10s
group_interval: 10s
repeat_interval: 1h
receiver: 'web.hook'
receivers:
- name: 'web.hook'
webhook_configs:
- url: 'http://127.0.0.1:5001/'
EOF
# Create Docker Compose file
echo -e "${YELLOW}[6/8] Creating Docker Compose configuration...${NC}"
cat > "$INSTALL_DIR/docker-compose.yml" << 'EOF'
version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus:/etc/prometheus
- prometheus_data:/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'
- '--web.enable-lifecycle'
restart: unless-stopped
grafana:
image: grafana/grafana:latest
container_name: grafana
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
restart: unless-stopped
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.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
restart: unless-stopped
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
restart: unless-stopped
alertmanager:
image: prom/alertmanager:latest
container_name: alertmanager
ports:
- "9093:9093"
volumes:
- ./alertmanager:/etc/alertmanager
restart: unless-stopped
volumes:
prometheus_data:
grafana_data:
EOF
# Set proper permissions
chmod 644 "$INSTALL_DIR"/{prometheus,grafana/provisioning/datasources,grafana/provisioning/dashboards,alertmanager}/*.yml
chmod 644 "$INSTALL_DIR/docker-compose.yml"
chown -R $DOCKER_USER:$DOCKER_USER "$INSTALL_DIR"
# Configure firewall
echo -e "${YELLOW}[7/8] Configuring firewall...${NC}"
if command -v firewall-cmd &> /dev/null; then
firewall-cmd --permanent --add-port=3000/tcp # Grafana
firewall-cmd --permanent --add-port=9090/tcp # Prometheus
firewall-cmd --permanent --add-port=9100/tcp # Node Exporter
firewall-cmd --reload
elif command -v ufw &> /dev/null; then
ufw allow 3000/tcp
ufw allow 9090/tcp
ufw allow 9100/tcp
fi
# Start the monitoring stack
echo -e "${YELLOW}[8/8] Starting monitoring stack...${NC}"
cd "$INSTALL_DIR"
sudo -u $DOCKER_USER docker compose up -d
# Verification checks
echo -e "${YELLOW}Performing verification checks...${NC}"
sleep 10
if sudo -u $DOCKER_USER docker compose ps | grep -q "Up"; then
echo -e "${GREEN}✓ Docker containers are running${NC}"
else
echo -e "${RED}✗ Some containers failed to start${NC}"
exit 1
fi
if curl -s http://localhost:9090 > /dev/null; then
echo -e "${GREEN}✓ Prometheus is accessible on port 9090${NC}"
else
echo -e "${RED}✗ Prometheus is not accessible${NC}"
fi
if curl -s http://localhost:3000 > /dev/null; then
echo -e "${GREEN}✓ Grafana is accessible on port 3000${NC}"
else
echo -e "${RED}✗ Grafana is not accessible${NC}"
fi
echo -e "${GREEN}Installation completed successfully!${NC}"
echo -e "${GREEN}Access URLs:${NC}"
echo -e " Grafana: http://localhost:3000 (admin/admin)"
echo -e " Prometheus: http://localhost:9090"
echo -e " Node Exporter: http://localhost:9100"
echo -e " cAdvisor: http://localhost:8080"
echo -e " Alertmanager: http://localhost:9093"
echo ""
echo -e "${YELLOW}Note: Change the default Grafana password after first login${NC}"
echo -e "${YELLOW}Installation directory: $INSTALL_DIR${NC}"
Review the script before running. Execute with: bash install.sh