Skip to main content

Prometheus - Docker Compose, Part 3: PostgreSQL Monitoring with PostgreSQL Exporter, Grafana Dashboard

587 words·
Prometheus Alertmanager Grafana PostgreSQL PostgreSQL Exporter Docker-Compose Monitoring
Table of Contents
Prometheus-Compose - This article is part of a series.
Part 3: This Article

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.12 # PostgreSQL & PostgreSQL Exporter Docker Compose Stack



PostgreSQL & PostgreSQL Exporter Containers
#

File and Folder Structure
#

# Create a directory for PostgreSQL
sudo mkdir -p /opt/postgres && cd /opt/postgres

Environment Variable File
#

# Create a .env file
sudo vi .env

# PostgreSQL credentials
DB_USERNAME=postgres
DB_PASSWORD=my_secure_password
DB_HOST=postgres
DB_NAME=postgres

Docker Compose Manifest
#

# Create a Docker Compose manifest
sudo vi docker-compose.yml
services:
  postgres:
    image: postgres:12
    container_name: postgres
    restart: unless-stopped
    ports:
      - 5432:5432
    volumes:
      - ./postgres-data:/var/lib/postgresql/data
    env_file:
      - .env
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: ${DB_NAME}
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 3

  postgres-exporter:
    image: prometheuscommunity/postgres-exporter
    container_name: postgres-exporter
    restart: unless-stopped
    ports:
      - 9187:9187
    env_file:
      - .env
    environment:
      DATA_SOURCE_NAME: "postgresql://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}/${DB_NAME}?sslmode=disable"
    depends_on:
      postgres:
        condition: service_healthy
# Create the container
sudo docker compose up -d

Verify the Exporter
#

# List the containers
docker ps

# Shell output:
CONTAINER ID   IMAGE                                   COMMAND                  CREATED          STATUS                    PORTS                                       NAMES
b9c75bd5090a   prometheuscommunity/postgres-exporter   "/bin/postgres_expor…"   14 seconds ago   Up 3 seconds              0.0.0.0:9187->9187/tcp, :::9187->9187/tcp   postgres-exporter
ee872b474b64   postgres:12                             "docker-entrypoint.s…"   14 seconds ago   Up 13 seconds (healthy)   0.0.0.0:5432->5432/tcp, :::5432->5432/tcp   postgres
# Curl the exporter metrics
curl http://localhost:9187/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

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 }}

Restart Docker Container
#

# Restart the Docker container
sudo docker compose restart



Dashboards
#

Grafana Dashboard
#

Open Webinterface
#

# Grafana webinterface
192.168.30.10:3000

Import the “Prometheus Postgres Exporter” Dashboard
#

Import the “Postgres Exporter" dashboard with the ID “9628”:

Go to: “Home” > “Dashboard”

Click “+ Create dashboard”

Select “Import dashboard”

Paste the dashboard ID “9628” and click “Load”

Select the “Prometheus” data source

Click “Import”


The dashboard should look like this:



Prometheus Webinterface
#

Open Webinterface
#

# Open the Prometheus webinterface
http://192.168.30.10:9090

Verify Endpoints
#

  • Select “Status” > “Target health”



Example Alert
#

Stop PostgreSQL Container
#

Stop the PostgreSQL Docker container:

# CD into the Docker Compose directory
cd /opt/postgres

# Stop the Docker container
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

Prometheus-Compose - This article is part of a series.
Part 3: This Article