How-to create a raspberry pi webserver cluster with Docker Swarm

I usually don’t blog in English but since I couldn’t find any good tutorial how to set up an raspberry pi cluster running docker swarm i thought i’ll write one based upon my experience and what i’ve stumbled upon searching for information on this. Feel free to use the comment section below with suggestions on how i can improve this tutorial.

I wont get in to any specifics on how docker works in general, so if you are new to docker then visit docker.com and their forum.

Index of this blogpost

Step 1 – Buy the hardware

Alright, let’s kick it off. In order to create this cluster you’ll need so shop some stuff:

    • 1 raspberry pi 3
    • 3 raspberry pi Zero (w or no w doesnt mather)
    • 1 raspberry pi Cluster hat
    • 1 raspberry pi cluster case
    • 5 Micro SD-card
    • 1 ethernet-cord

 

Everything mentioned above is pretty easy to come-by, except the raspberry pi Z. You can usually only buy one of this at the time, so make use of your friends and force them to buy one for you 🙂

For this project you will also be needing access to:

    • 
A computer (I’m using a Macbook Pro Touchbar 2016)
    • 1 free slot on your router for ethernet connection

 

This is needed in order to format the SD-cards and also for SSH:ing into the the pies.

Step 2 – Configure the hardware

The hardware set up is pretty basic. You’ll need to mount the cluster hat to your raspberry pi and the raspberry pi Z on the cluster-hat. Here’s a video showing how to set it up:

Note that there are some small texts on the raspberry pi cluster hat stating what slot the raspberry pi Z are in.

Step 3 – Configure the software on the Raspbian Pies

The cluster hat project has images for you to download – which is awesome. This saves you a lot of time. So start by downloading them here.

There are 5 images, one for the controller which is the main raspberry pi and 4 images for the raspberry pi Z.

Then you’ll need to prepare and move the images you just downloaded to the SD-cards. Since I’m using a Macbook this guide will describe on how to do it on a Mac. If your’e using a windows computer then visit this page to learn how to do it.

Start by inserting the SD-cards to your Macbook. The newest Macbook don’t have an SD-card slot so you will need a dongle/adapter, but the older once do have a SD-card slot.

After mounting start the disk utility-app and format the SD-card with FAT32. The SD-card is now formatted and ready to get the image(s) on them.

Then hit up a new terminal window and do the following commands. Start by identifying the name of the SD-card by doing:

diskutil list

Identify the disk (not the partition) of your SD card, e.g. disk4, not disk4s1.

Unmount your SD card by using the disk identifier, to prepare it for copying data:

diskutil unmountDisk /dev/disk<disk# from diskutil

Where disk is your BSD name e.g. diskutil unmountDisk /dev/disk4

Copy the data to your SD card:

sudo dd bs=1m if=image.img of=/dev/rdisk<disk# from diskutil> conv=sync

where disk is your BSD name e.g:

sudo dd bs=1m if=2017-07-05-raspbian-jessie.img of=/dev/rdisk4 conv=sync

This may take a while but to make sure everything is running and the data is being transferred to the SD-card you can hit CTRL + T to see the progress.

When the data transfer is done and the image is on the SD-card you’ll need to create a new file on your desktop called ”ssh” (just ”ssh” and nothing more”. The SD-card will probably be named ”boot” now and you’ll need to put that file (the ”ssh” file) on the SD-card. This file will enable SSH on your Raspbian Pie which will make everything a bit easier.

Repeat this process for all 5 SD-cards. Once that is done – put the SD-cards in to your Raspbian. Where the controller image/SD-card should go on the main Raspbian Pie 3 and the other SD-card (p1, p2, p3 and p4) on the other raspberry pi’s Z.

Step 4 – Start the cluster

Plug in the ethernet cable and the MicroUSB-cable in to your main raspberry pi (controller). Your controller is now online and you will be available on your local network. Next you will need to figure out what local IP address your router has assigned your Raspbian Pie controller. I’m using an app called ”inet network scanner” which scans the network and prompts the device on the network and what ip-addresses they have. There are a tons of ways of doing this.

The ip will be something like 192.168.0.X or 10.0.1.X.

Step 5 – Activate the cluster (p1, p2, p3 and p4)

Now that we know what IP our controller has we can access it by SSH. The default username for the pies are ”pi” and password is ”raspberry” Open a terminal window and enter the following:

ssh pi@YOUR-IP

The terminal will now prompt use asking you if you really want to connect to this device and that your fingerprint will be logged. Type yes and hit enter,

You will now be prompted to enter the password, enter ”raspberry” and you will now have access.

Since we downloaded the images from the cluster hat-project there are some already installed packages for controlling your cluster-hat:

cluster-hat on all (This will turn on your raspbian pies Z)
cluster-hat off all (This will turn off your raspbian pies Z)

So in the terminal type:

cluster-hat on all

The LED’s on your cluster hat should now be orange meaning that the full cluster is now online.

Step 6 –  Configurations

There are some important configurations on all (5) of the Raspbian Pies. These are password change, expand the filesystem and updates, install fail2ban and only allow access with SSH-keys. This following steps are importing and will greatly improve the security of you cluster.

Step 6.1 – Change password

The first thing you should do is to change the ”raspberry” password since its something that default.This should be done on In the terminal type:

passwd

The terminal will now prompt you to enter the current password (”raspberry”) and then the new password twice. Please use a secure password with some capital letters and some signs like ”!” or ”#”.

Step 6.2 – Expand the filesystem

In the terminal type:

sudo raspi-config

This will prompt and UI-like window where you can make some basic changes. Here you’ll need to go down to ”Advanced options” and then ”Expand filesystem”. Hit enter and then the guide will as you to do a reboot, do that.

Step 6.3 – Updates

The next step is to perform updates. First, update your system’s package list by entering the following command:

sudo apt-get update

Next, upgrade all your installed packages to their latest versions with the command:

sudo apt-get dist-upgrade

Step 6.4 – Install fail2ban

This is a service that will auto block some login attempts. No configuration is needed, just install the package with typing the following in the terminal:

sudo apt-get install fail2ban

Step 6.5 – Only allow SSH-access thru SSH-keys

This will be one of the most important security update we can do. This will only allow your local computer to access the raspberry pi’s thru SSH. This also means that you can’t login thru SSH from another computer with password.

Start by opening a new terminal on your local machine and type the following:

ssh-copy-id pi@<RPI.IPADDRESS>

Step 7 – Install docker (which includes swarm-functionality)

So, finally we get to the part that most likely got you here; installing docker swarm on your Raspbian Pie cluster.

The first step is to ssh in to all of your devices, yes – all five of them. Once you have a terminal for all of them type the following in each terminal:

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

The progress of installing docker should now begin and it will probably take a while. Once that is done you will now have docker installed.

Step 8 – Build the docker swarm cluster

One we have docker installed on all of our machines we should now make a swarm. On the controller, the main Raspbian Pie, type the following in the terminal:

sudo docker swarm init --advertise-addr

Replace MANAGER-IP with the ip-number of your main raspberry pi/controller.

This will initiate the swarm and make the controller to the manager.

Then on the 5 Raspbian Pies Z type the following in their respective terminal:

sudo docker swarm join \
--token SUPERLONG-TOKEN \
:PORT

This will join the the p1, p2, p3 and p4 into the swarm and slaves. Remember to change the token and the ip-number

Now you have a docker swarm cluster running, cool huh? But before we can start messing around with docker swarm we need to do one last thing in the controller terminal, type:

sudo iptables -P FORWARD ACCEPT

This will enable the cluster hat again after the installation of docker.

Step 9 – Docker swarm is now ready and ready to launch services

In this tutorial we will create a web-server. Since docker is based upon containers and services (for swarm) we can utilize this. I’ve messed around a lot of the top images on hub.docker.com but no-one of them really suited my needs, a simple web server with some custom code.

Also, since we are using raspberry pi’s we will need to use ”ARM” or ”RPI” images that optimized for raspberry pi. Not all of the images on hub.docker.com will work on your cluster. So I’ve found that creating your own image is probably the best for running a web server with some custom code.

Step 10 – Create your own docker image and repository

First of start by making an account on http://hub.docker.com. This account will enable 1 free private repository (like GitHub but not with so many functions). After you have made a new account go to https://hub.docker.com/add/repository/ and create the repository. Choose private and enter a name and a short description.

Once that I done we can start with creating our own docker image locally. This will need you to install docker locally on your computer. If you haven’t already done that you can download docker here: https://docs.docker.com/engine/installation/

Next up, we need to create a directory/folder where we keep our files for the imags. I’ve personally use documents/project/ as directory for my project, but hey choose whatever floats your boat.

So create a new folder, with the same name as your repository and go in to it. Here we will create a new folder called ”code” which we will store our code. In this folder create a file named ”index.php” and edit it to the following:

<?php echo "hello world";

Then save the file and go back to your project folder. In this folder you will need to create a new file called ”Docker-file”, no extensions. This file is necessary for the docker image building processes and specifies what images (apache and php) that are needed to create our web server. In this ”Docker-file” put the following:

FROM sergeytykhonov/rpi-php:7.1.4-apache
COPY code/ /var/www/html/

What this does is that it’s telling Docker to include the ARM-build of sergeytykhonov/rpi-php which enables php and apache. It also tells docker that our code in the ”code”-folder should be put to the standard apache folder (/var/www/html/).

Now everything is ready and we can build our image.

In our local terminal type:

cd documents/projects/NAME-OF-THE-PROJECT

And now we are in the folder with the ”Docker-file”. Start by loggin in to docker with:

docker login —username YOUR-DOCKER-USERNAME —password YOUR-DOCKER-PASSWORD

Then build the image with the following command:

sudo docker build -t NAME-OF-YOUR-IMAGE .

Then tag the image with the following:

sudo docker tag NAME-OF-YOUR-IMAGE YOUR-DOCKER-USERNAME/REPOSITORY-NAME

Then push it to docker hub with the following command:

sudo docker push YOUR-DOCKER-USERNAME/REPOSITORY-NAME

On your repository on http://hub.docker.com you should now see an update on your private repository.

Step 11 – Start the service in the swarm

Alright, now that our custom image with our custom code is stored on the private repository we can now ship the image and run it as an service on our swarm.

SSH on to your controller and type the following to login to your docker-account, which is needed in order to access your private repository:

docker login —username YOUR-DOCKER-USERNAME —password YOUR-DOCKER-PASSWORD

Then let’s start the service:

sudo docker service create --name NAME-OF-SERVICE --publish 1337:80 --with-registry-auth YOUR-DOCKER-USERNAME/REPOSITORY-NAME

You should now get an message saying that the docker service is created and that it will load the docker service in the background.

In the terminal, type the following to see status:

sudo docker service ls

This tells us that everything looks good and that our service is created. It usually takes a couple of minuets to start the service.

To check that everything is good we can type the following:

sudo docker services ps NAME-OF-SERVICE

This tells us that everything looks good and that our service is created. It usually takes a couple of minuets to start the service.

Now is an excellent time to browse social media on your smartphone while it’s preparing and running the service. After 2-3 minuets you can type:

sudo docker service ls

The replicas should now be 1/1 and the service should now be running. You can visit http://IP-TO-CONTROLLER:1337 to visit the page. This should show you the ”hello world” text.

Step 12 – Scale the service to your p1, p2, p3 and p4

Now that the service is up and running on our controller we can scale the service to our other pies (p1, p2, p3 and p4) which is done by typing the following:

sudo docker service scale NAME-OF-SERVICE=5

This will scale your service to 5, meaning that it will run 1 instance of your service on every raspberry pie (controller, p1-5).

You can track the progress by typing the following in the terminal:

sudo docker service ls

Step 13 – Update the service

So now you got the POC (proof of concept) up and running and you want to edit the code and maybe add some awesome features to your ”index.php” file or add whatever you like.

So after you have done your changes to your file(s) in the folder ”code” on your local machine, then we need to build a new image, push it to the private repository and update the service, with the new image, to our swarm.

So after you have made the changes you like, open a terminal for your local machine and type:

cd PATH-TO-YOUR-FOLDER-WHERE-DOCKERFILE-IS
sudo docker login --username USERNAME --password PASSWORD
sudo docker build -t NAME-OF-SERVICE .
sudo docker tag NAME-OF-YOUR-IMAGE YOUR-DOCKER-USERNAME/REPOSITORY-NAME
sudo docker push YOUR-DOCKER-USERNAME/REPOSITORY-NAME

Your repository has now been updated with your image. The next step is to update the running service on your swarm. This is done by ssh:ing in to your controller thru terminal and typing:

sudo docker service update --image USERNAME/REPOSITORY-NAME NAME-OF-SERVICE

The service will now update itself and you can follow the progress with the following command:

sudo docker service ps NAME-OF-SERVICE

You have now a running raspberry pi cluster with docker swarm that you can update with your own code. Enjoy! Feel free to use the comments function below for feedback and or questions.

Here are some useful links: