Grafana Monitoring on a Raspberry Pi

Published | 4 min read

As you might have seen from my last few posts I have quite a lot running on my Raspberry Pi.

I am currently using a Raspberry Pi 2 B which is a great device but only has 1GB of RAM and 900 MHz CPU. So I am a little worried sometimes that I am going to overload it with all the docker services I am running on it.

I use Grafana a lot at work and love it, so I thought it would be good to use it to monitor my Raspberry Pi.

Monitoring Aim

With any monitoring, it is important to know what you want to keep an eye on.

In my case I am interested in the following:

  • CPU - If the CPU ends up running at 100% a lot of the time, I might need to scale down the services running on it
  • Memory - With only 1GB of memory I need to keep an eye on how much I run on it.
  • Hard Disk Space - I have a 32GB SD card in my Pi but I have had one fill up before which makes the whole thing unresponsive.
  • Container data - I want to know which containers are causing high CPU and Memory usage.

What we need

There are probably quite a few services that work with Grafana for monitoring. However, I am using the following:

  • Grafana - obviously!
  • Prometheus - for gathering the data in a time series.
  • cAdvisor - A container monitor from Google to monitor the resources used by containers.
  • Node Exporter - Prometheus exporter for hardware and OS metrics
  • Docker - obviously
  • Traefik - I use this as my reverse proxy if you don’t have a reverse proxy set up you can follow my previous post, Traefik vs Nginx for Reverse Proxy with Docker on a Raspberry Pi.

Docker Compose Set up

I will go straight to the Docker Compose file you need and will explain what you need to change for your setup:

version: '3.4'

    image: prom/prometheus:latest
    container_name: monitoring_prometheus
    restart: unless-stopped
      - ./data/prometheus/config:/etc/prometheus/
      - ./data/prometheus/data:/prometheus
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - 9090
      - cadvisor:cadvisor
      - node-exporter:node-exporter
      - pi

    image: prom/node-exporter:latest
    container_name: monitoring_node_exporter
    restart: unless-stopped
      - 9100
      - pi

    image: braingamer/cadvisor-arm:latest
    container_name: monitoring_cadvisor
    privileged: true
    restart: unless-stopped
      - /:/rootfs:ro
      - /var/run:/var/run:rw
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
      - /dev/kmsg
      - 8080
      - pi

    image: grafana/grafana:latest
    container_name: monitoring_grafana
    restart: unless-stopped
      - prometheus:prometheus
      - ./data/grafana:/var/lib/grafana
      - GF_USERS_ALLOW_SIGN_UP=false
      - 'traefik.enable=true'
      - 'traefik.http.routers.grafana.rule=PathPrefix(`/grafana{regex:$$|/.*}`)'
      - ''
      - 'traefik.frontend.headers.customRequestHeaders=Authorization:-'
      - pi

    external: true

You only need to change the following environment variables to match the domain for your Raspberry Pi. If you are running locally you could use localhost and http://localhost/grafana.


You will notice I am using braingamer/cadvisor-arm:latest for cAdvisor. This is because the official Google image doesn’t support ARM and is marked as deprecated. Of course, if you wanted to you could build your own docker image.

This is the Prometheus config file I am using, prometheus.yml:

# my global config
  scrape_interval: 120s # By default, scrape targets every 15 seconds.
  evaluation_interval: 120s # By default, scrape targets every 15 seconds.
  # scrape_timeout is set to the global default (10s).

  # Attach these labels to any time series or alerts when communicating with
  # external systems (federation, remote storage, Alertmanager).
    monitor: 'my-project'

# Load and evaluate rules in this file every 'evaluation_interval' seconds.
  # - "alert.rules"
  # - "first.rules"
  # - "second.rules"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: 'prometheus'

    # Override the global default and scrape targets from this job every 5 seconds.
    scrape_interval: 120s

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

      - targets: ['localhost:9090', 'cadvisor:8080', 'node-exporter:9100']

Dashboard Set Up

This is what my Grafana dashboard looks like. If you want something similar then you can copy my dashboard json.

Grafana Dashboard

There are quite a few other metrics available from node-exporter and cAdvisor I could have used. Let me know in the comments if find any useful ones.


Stack vs Heap Memory - What are the differences?

Stack vs Heap Memory - What are the differences?

  • 30 November 2022
In modern programming languages such as C# or Java, we tend to take memory management for granted. Gone are the days when we need to call malloc to request enough memory for our variables. Luckily a lot of that is done for us by the runtimes so we do...
Code Katas: Can They Make You A Better Developer?

Code Katas: Can They Make You A Better Developer?

  • 21 November 2022
They say “practice makes perfect”, although I much prefer “practice makes improvement”. Either way, how do you practice being a programmer? If you are already working as a software developer then you will be getting some practice from working on larg...
Git Flow vs GitHub Flow

Git Flow vs GitHub Flow

  • 10 November 2022
Losing code that you have spent hours writing can be painful, which is why we use version control (or source control) to store our code and manage changes. Version control is even more important if you are working in a team, without it code, changes ...
I Posted on YouTube Consistently for 1 Month. This is What Happened!

I Posted on YouTube Consistently for 1 Month. This is What Happened!

  • 02 November 2022
As part of my creative sabbatical, I have been posting a new software development video on my YouTube channel every Monday and Friday. It takes a long time to grow on YouTube, and I knew this going in but I have been pleasantly surprised with my grow...
Bitwise Operators and WHY we use them

Bitwise Operators and WHY we use them

  • 26 October 2022
Bitwise operators are one of those concepts that a lot of programmers don’t understand. These are not used a great deal anymore so you can get away with not knowing them but they can still come in handy for a number of different scenarios. If you end...
8 Data Structures you NEED to Know

8 Data Structures you NEED to Know

  • 26 October 2022
You can get pretty far in programming without understanding Data Structures, but eventually, you are going to need to know them, understand how they work and when to use them. What is a data structure? A da...
Binary Numbers Explained for Programmers

Binary Numbers Explained for Programmers

  • 21 October 2022
Everyone knows that computers run on ones and zeros. This is because CPUs are made up of billions of transistors, which are basically just on-off switches. Any code you write needs to be processed by a computer and therefore has to be converted to b...
Beginners Guide to Programming

Beginners Guide to Programming

  • 12 October 2022
A lot of my articles are aimed at intermediate to advanced developers, but as part of my creative sabbatical, I am working on creating content for those just starting out. So in this post I will be covering some of the many questions that beginner pr...