Dockerize Grafana And Deploy It on A Raspberry Pi Using AWS IoT Greengrass

Frank Haubenschild
9 min readSep 24, 2021

AWS Greengrass extends Amazon Web Services towards IoT devices. With Greengrass for example, you can collect IoT data on your devices and securely upload them for further processing to the cloud. Besides this, you can provision your devices. Greengrass supports Lambda functions which you can deploy. It also supports deploying your services through Docker images onto your hardware.

Photo by Ian Taylor on Unsplash

Let’s not just deploy a Hello-World Docker container onto your IoT Device and instead take a useful Grafana instance. The following steps are needed to get everything up and running:

  1. Set up your Raspberry Pi + Docker installation
  2. Install and Configure AWS IoT Greengrass Core Software on your Pi
  3. Prepare a Docker Image with Grafana and upload it to S3
  4. Write a Greengrass recipe and deploy the Docker image via Greengrass on your device
  5. Getting component insights using the LocalDebugConsole

#1: Set up your Raspberry Pi + Docker installation

If you’re starting from scratch you first need to flash your Pi with a decent Linux Distro i.e. Raspberry Pi OS. A good installation tutorial can be found here [5]. After the system has booted up successfully follow the next steps to get Docker up and running:

Always take care that your system is bleeding edge

$ sudo apt-get update && sudo apt-get upgrade

Install Docker

$ curl -sSL https://get.docker.com | sh

Add a Non-Root User to the Docker Group
If you do not want to run the Docker containers as a privileged user (root user) and do not want to add a sudo-prefix to all your docker commands, you can add a non-root user to the Docker group which allows this user to run Docker commands. The following command adds the current user to the docker group:

$ sudo usermod -aG docker ${USER}
$ groups ${USER}
pi : pi adm dialout cdrom sudo audio video plugdev games users input netdev spi i2c gpio lpadmin docker

Enable Docker system service

$ sudo systemctl enable docker

Install Docker compose (via pip3)

$ sudo apt-get install libffi-dev libssl-dev
$ sudo apt install python3-dev
$ sudo apt-get install -y python3 python3-pip
$ sudo pip3 install docker-compose

Check and run a “Hello World”-container

$ docker — version
Docker version 20.10.7, build f0df350
$ docker run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.....

#2: Install and Configure AWS IoT Greengrass Core Software on your Pi

After setting up the Pi and having installed Docker you now have to install the so-called Greengrass IoT Core Software [2]. The Greengrass Core Software kind of acts as a man-in-the-middle between your IoT device and the AWS cloud. It handles the connections (reconnections in case of dropdowns) towards the cloud securely and supports you with new functionality such as deploying services as Lambda functions or installing and running Docker containers on your device. To install the Greengrass IoT Core Software the following steps are needed:

Install the Java runtime environment

$ sudo apt install default-jdk
$ java -version
openjdk version “11.0.11” 2021–04–20
OpenJDK Runtime Environment (build 11.0.11+9-post-Raspbian-1deb10u1)
OpenJDK Server VM (build 11.0.11+9-post-Raspbian-1deb10u1, mixed mode)

Provide AWS credentials to the Greengrass Installer

To link your Greengrass Core Software instance with your AWS account you have to create an AWS user. You can find a policy that includes a minimum set of actions that the Greengrass installer requires to provision AWS resources here. Once the user has been created note down its access key id and the secret access key and export it via the following environment variables on your Pi:

$ export AWS_ACCESS_KEY_ID=<YOUR_ACCESS_KEY_ID>
$ export AWS_SECRET_ACCESS_KEY=<YOUR_SECRET_ACCESS_KEY>

Download the IoT Greengrass Core software

Using the following curl command you can download the latest version of the Greengrass Core Software called nucleus. Unzip the zip archive to your machine. The nucleus component is the only mandatory Greengrass component to run the AWS IoT Greengrass Core Software on your device.

$ cd ~
$ curl -s $ https://d2s8p88vqu9w66.cloudfront.net/releases/greengrass-nucleus-latest.zip > greengrass-nucleus-latest.zip
$ unzip greengrass-nucleus-latest.zip -d GreengrassCore && rm greengrass-nucleus-latest.zip

Run the Java Installer

If you want you can change the aws-region, the thing-, and thing-group-name option to your needs. Also, the role-name and its alias can be renamed.

$ sudo -E java -Droot=”/greengrass/v2" -Dlog.store=FILE \
-jar ./GreengrassCore/lib/Greengrass.jar \
— aws-region eu-central-1 \
— thing-name MyGreengrassCore \
— thing-group-name MyGreengrassCoreGroup \
— tes-role-name GreengrassV2TokenExchangeRole \
— tes-role-alias-name GreengrassCoreTokenExchangeRoleAlias \
— component-default-user ggc_user:ggc_group \
— provision true \
— setup-system-service true \
— deploy-dev-tools true

Running the Greengrass Core Java Installer does the following configuration on your device and within your AWS account:

  • Install of the nucleus component on your Pi
  • Register your device as an IoT Thing and download the certificate which allows your device to communicate securely with the AWS cloud.
  • Add your device’s AWS IoT Thing to a thing group. Groups can be used to manage a fleet of Greengrass core devices. It makes the handling of multiple devices much easier. I.e. you can request to install and run a Docker container directly to hundreds of devices instead of picking one by one.
  • Creation of an IAM role that allows the Greengrass core device to interact with AWS services — by default permission is only granted to the Amazon Cloudwatch Logs and AWS IoT.
  • By setting the option — deploy-dev-tools true the AWS IoT Greengrass command-line interface (greengrass-cli [3]) gets installed. This CLI is helpful for local development but should never be deployed on a production system.

The installation may take a minute or two. Once it succeeds you should see a Healthy Core Device within the AWS IoT Core Management Console. Now you are ready to install Greengrass components on your device.

The Greengrass core device status shows you if your device is ready to rumble ;-)

#3: Prepare a Docker Image with Grafana and upload it to S3

As an example, let’s assume you want to install Grafana [9] on your Pi via Greengrass. The following command lines are showing you how to create a docker image for Grafana. For readers who want to understand each and single line please have a detailed look at the following tutorial [6].

# Create all necessary directoriesmkdir -p $HOME/docker/grafana/data 
mkdir -p $HOME/docker/grafana/provisioning
mkdir -p $HOME/docker/compose-files/grafana
# Extract grafana default configuration file
cd $HOME/docker/grafana
docker run — rm — entrypoint /bin/bash grafana/grafana:latest -c ‘cat $GF_PATHS_CONFIG’ > grafana.ini
# Set grafana directory to the default Grafana user ID
chown 472:472 $HOME/docker/grafana/data

Create .env file with the Grafana credentials for the admin user:

# Create a .env file with the Grafana credentials
# $HOME/docker/compose-files/grafana/.env GF_SECURITY_ADMIN_USER=admin GF_SECURITY_ADMIN_PASSWORD=initialpassword

Finally, create a Docker compose file at $HOME/docker/compose-files/grafana/docker-compose.yml

version: "3.3" 
services:
grafana:
image: grafana/grafana:latest
container_name: grafana
restart: always
ports:
— "3000:3000" # expose for localhost
volumes:
— $HOME/docker/grafana/data:/var/lib/grafana # data path
— $HOME/docker/grafana/grafana.ini:/etc/grafana/grafana.ini
— $HOME/docker/grafana/provisioning:/etc/grafana/provisioning
environment:
— GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource
— GF_SECURITY_ADMIN_USER=${GF_SECURITY_ADMIN_USER}
— GF_SECURITY_ADMIN_PASSWORD=${GF_SECURITY_ADMIN_PASSWORD}

Start the Grafana container locally:

cd $HOME/docker/compose-files/grafana 
docker-compose up -d

Test if you can access your Grafana instance within a browser via the URL http://127.0.0.1:3000 . You should see the following login screen.

After we have created and successfully tested our docker container you can delete the image and the container from your PI. The final deployment will be done via Greengrass. Greengrass supports pulling Docker images from the following sources:

  • Amazon Elastic Container Registry (Amazon ECR)
  • S3 bucket
  • Public Docker Hub repository and Public Docker Trusted Registry

In this tutorial, we want to use Amazon Simple Storage Service (S3). Thus, we first create a single archive holding our docker image, and second we upload the Grafana tar-archive to our bucket unique-bucket-name.

docker save grafana/grafana:latest > grafana.tar

To give Greengrass the necessary permissions to pull the docker image from S3 we have to add the following policy to the Greengrass role which the java-installer has created before.

{ 
"Version": "2012–10–17",
"Statement”: [
{
"Action": [
"s3:GetObject*",
"s3:GetBucket*",
"s3:List*"
],
"Resource": [
"arn:aws:s3:::unique-bucket-name",
"arn:aws:s3:::unique-bucket-name/*"
],
"Effect": "Allow"
}
]
}

#4: Write your Greengrass recipe and deploy the docker image on your Pi

Deploying Greengrass components can be either done via the AWS Management Console or via the AWS-CLI [8]. First, I’m gonna show usage of the AWS Management Console to create a Greengrass component. For this, we need to write a so-called recipe [7]— either in JSON- or in YAML representation. You have to give each component a proper name and within Lifecycle, you specify from where the Docker image can be pulled from and what are the docker run parameters to execute the container.

---
RecipeFormatVersion: '2020-01-25'
ComponentName: com.example.GrafanaDockerComponent
ComponentVersion: '1.0.0'
ComponentDescription: 'Greengrass Component with Grafana'
ComponentPublisher: Amazon
Manifests:
- Platform:
os: linux
Lifecycle:
Install:
Script: docker load -i {artifacts:path}/grafana.tar
Run:
Script: docker run -p 3000:3000 --rm grafana/grafana
Artifacts:
- URI: s3://unique-bucket-name/artifacts/com.example.GrafanaDockerComponent/1.0.0/grafana.tar

After having a recipe we create the component via the AWS Management console.

Having created a component we need to create a so-called deployment. You can either use an existing deployment for a given device or a group of devices or you can create a new deployment from scratch. Note that a particular device can only have one deployment at a time. Inside a deployment, you can have multiple components but unfortunately, the number of deployments is limited to one.

You can check on your Pi the Greengrass log files under /greengrass/v2/logs — either the Greengrass core log file in greengrass.log or each component log file you will find log traces. Our Grafana component will write logs to com.example.GrafanaDockerComponent.log. Another helpful development tool is the AWS managed component aws.greengrass.LocalDebugConsole which gives you a web frontend to check each component's status. If you have successfully arrived at this state, you should now have your Grafana instance running at http://127.0.0.1:3000

For those readers who prefer using the AWS-CLI find the following commands how to create a component version and finally how to create a deployment:

# save our component recibe from above into a file (recipe.yaml)aws greengrassv2 create-component-version  --inline-recipe fileb://recipe.yaml# an example deployment to a group could look like - save this into a separate file (deployment.json){
"targetArn": "arn:aws:iot:eu-central-1:<your-id>:thinggroup/MyGreengrassCoreGroup",
"components": {
"com.example.GrafanaDockerComponent": {
"componentVersion": "1.0.0"
}
}
}
# finally run the deployment
aws greengrassv2 create-deployment --cli-input-json file://deployment.json

#5: Getting component insights using the LocalDebugConsole

If you have installed the Greengrass core software with the option deploy-dev-tools true you can generate a username/password for the graphical Web-Frontend provided by the AWS component aws.greengrass.LocalDebugConsole which you have to install manually either via command line or via the AWS IoT Management console. The following screenshots show how to install this public component via the console.

#1: Within the IoT Service search for aws.greengrass.LocalDebugConsole underneath the Public components — select the component name.
#2: Press the Deploy button to continue.
#3: Choose if you want this component to be deployed under an existing deployment or if you want to create a new deployment — note only one deployment per device.
#4: Finally give your deployment a meaningful name and specify the target (either one particular device or a group of devices).

If the component was deployed successfully and is in the state running you need to generate a password via the greengrass-cli which is located in /greengrass/v2/bin to get access to the Web-Frontend.

$ sudo ./greengrass-cli get-debug-passwordUsername: debug
Password: SDFfdsdfjsdfsdfjsdklfsdfjksdflk Password will expire at: 2021-08-17T13:26:39.453454534+02:00

Afterwards, you can access the web-frontend via https://127.0.0.1:1441

Using this web-frontend you can start and stop components, see their settings and their dependency graph.

References

  1. [Run a Docker container] https://docs.aws.amazon.com/greengrass/v2/developerguide/run-docker-container.html
  2. [Getting started with AWS IoT Greengrass V2] https://docs.aws.amazon.com/greengrass/v2/developerguide/getting-started.html
  3. [AWS IoT Greengrass V2 CLI Reference] https://docs.aws.amazon.com/cli/latest/reference/greengrassv2/index.html
  4. [AWS IoT Greengrass component recipe reference] https://docs.aws.amazon.com/greengrass/v2/developerguide/component-recipe-reference.html
  5. [Setting up your Raspberry Pi Tutorial] https://projects.raspberrypi.org/en/projects/raspberry-pi-setting-up
  6. [Setting up Grafana on Raspberry Pi with Docker (compose)] https://blog.anoff.io/2021-01-howto-grafana-on-raspi
  7. [AWS IoT Greengrass component recipe reference] https://docs.aws.amazon.com/greengrass/v2/developerguide/component-recipe-reference.html
  8. [AWS Command Line Interface] https://aws.amazon.com/cli
  9. [Grafana] https://grafana.com

--

--

Frank Haubenschild

Dad, Software Engineer, Photographer, Reef- & Bee-Keeper, Founder, Drone Pilot — 🤓 💻 📷 🐝 🐠 💡👨‍✈️