Overview #
I’m using the following Ubuntu 24.04 based servers in this tuturial:
192.168.30.10 # Prometheus Docker Compose stack
192.168.30.11 # Nginx Container, Nginx Exporter Container
Nginx & Nginx Exporter Containers #
File and Folder Structure #
# Create a directory for Nginx
sudo mkdir -p /opt/nginx && cd /opt/nginx
The file and folder structure looks like this:
nginx
├── docker-compose.yml
└── nginx-status.conf
Nginx Configuration: nginx-status.conf #
# Create a Nginx configuration file for the Nginx metrics
sudo vi nginx-status.conf
server {
listen 8080;
# Optionally: Allow access only from localhost
# listen 127.0.0.1:8080;
server_name nginx-exporter; # Define a custom server name
location /status {
stub_status;
}
}
Docker Compose Manifest #
# Create a Docker Compose manifest
sudo vi docker-compose.yml
services:
nginx:
image: nginx:latest
container_name: nginx
restart: unless-stopped
ports:
- 8080:8080 # Nginx metrics
- 80:80 # Nginx default site
volumes:
- ./nginx-status.conf:/etc/nginx/conf.d/status.conf:ro
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8080/status || exit 1"]
interval: 10s
timeout: 5s
retries: 3
nginx-exporter:
image: nginx/nginx-prometheus-exporter:latest
container_name: nginx-exporter
restart: unless-stopped
ports:
- 9113:9113
environment:
- NGINX_HOST=http://nginx:8080
- NGINX_STATUS_PATH=/status
depends_on:
nginx:
condition: service_healthy
# Create the container
sudo docker compose up -d
Verify the Nginx Metrics & Exporter #
# List the containers
docker ps
# Shell output:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
539033beb213 nginx/nginx-prometheus-exporter:latest "/usr/bin/nginx-prom…" 36 seconds ago Up 25 seconds 0.0.0.0:9113->9113/tcp, :::9113->9113/tcp nginx-exporter
d5c7d6df0d97 nginx:latest "/docker-entrypoint.…" 36 seconds ago Up 35 seconds (healthy) 0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp nginx
# Curl the Nginx metrics
curl http://localhost:8080/status
# Shell output:
Active connections: 1
server accepts handled requests
6 6 6
Reading: 0 Writing: 1 Waiting: 0
# Curl the Nginx Exporter
curl http://192.168.30.11:9113/metrics
Prometheus Configuration #
Prometheus Configuration: prometheus.yml #
# Adapt the Prometheus configuration
sudo vi prometheus_conf/prometheus.yml
# prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 10s
rule_files:
- rules.yml
alerting:
alertmanagers:
- scheme: http
static_configs:
- targets: [ 'alertmanager:9093' ]
scrape_configs:
# Prometheus Server
- job_name: 'Prometheus-Server'
static_configs:
- targets:
- localhost:9090
# Linux Servers / Node Exporter
- job_name: 'Linux-Server'
static_configs:
- targets:
- 192.168.30.11:9100
- 192.168.30.12:9100
# MySQL Server
- job_name: 'MySQL-Server'
params:
auth_module: [client] # Specify authentication mode
scrape_interval: 5s
static_configs:
- targets: ['192.168.30.11:3306']
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: 192.168.30.11:9104
# PostgreSQL Server
- job_name: 'Postgres-Server'
static_configs:
- targets: ["192.168.30.12:9187"]
relabel_configs:
- source_labels: [__address__]
target_label: instance
- target_label: __address__
replacement: 192.168.30.12:9187
# Nginx Webserver
- job_name: 'Nginx-Webserver'
metrics_path: /metrics
static_configs:
- targets: ['192.168.30.11:9113']
Prometheus Configuration: rules.yml #
# Adapt the rules.yml configuration
sudo vi prometheus_conf/rules.yml
# rules.yml
groups:
- name: NodeExporter
rules:
- alert: InstanceDown
expr: up{job="Linux-Server"} == 0
for: 1m
- name: MysqldExporter
rules:
- alert: MysqlDown
expr: mysql_up == 0
for: 0m
labels:
severity: critical
annotations:
summary: MySQL down (instance {{ $labels.instance }})
description: "MySQL instance is down on {{ $labels.instance }}\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"
- name: PostgresExporter
rules:
- alert: PostgresDown
expr: pg_up == 0
for: 0m
labels:
severity: critical
annotations:
summary: PostgreSQL down (instance {{ $labels.instance }})
description: |
PostgreSQL instance is down on {{ $labels.instance }}
VALUE = {{ $value }}
LABELS = {{ $labels }}
- name: NginxExporter
rules:
- alert: NginxInstanceDown
expr: up{job="Nginx-Webserver"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: Nginx instance down
description: "Nginx instance {{ $labels.instance }} is unreachable."
Restart Docker Container #
# Restart the Docker container
sudo docker compose restart
Prometheus Webinterface #
Open Webinterface #
# Open the Prometheus webinterface
http://192.168.30.10:9090
Verify Endpoints #
- Select “Status” > “Target health”
Example Alert #
Stop Nginx Container #
Stop the Nginx Docker containers:
# CD into the Docker Compose directory
cd /opt/nginx
# Stop the Docker containers
sudo docker compose down
Verify the Prometheus Alert #
# Verify the alert in the Prometheus webinterface
http://192.168.30.10:9090/alerts
Verify the Alertmanager Alert #
# Verify the alert in the Prometheus webinterface
http://192.168.30.10:9093/#/alerts