So you’ve just bought a Raspberry Pi. Now what? What can I use this credit card sized computer for? It only has a 900Mhz processor! Don’t let this become another wasted project that you won’t be able to find a use for. With the following hints and tips you will be able to use your Raspberry Pi as a Docker Host in no time.
If you are not a newbie, then perhaps you are a DevOp who has heard of Docker. Well now is your perfect opportunity to test Docker and Docker Containers on your own kit. I would recommend the Raspberry Pi 2 which comes with 1GB RAM and 4 cores in the processor. I have also tried this on the Model B with 512MB of RAM and a single core processor and it all worked fine, just a little slower.
Using an RPI Docker Host
In this blog we will look at using a Raspberry PI 2 as a Docker host device. Yes, an RPI Docker Host. The Pi will run with an 8GB SD card or MicroSD, though we don’t need a lot of space for the host OS or Docker containers and associated images.
The RPI image that I am using can be downloaded from the Hypriot Blog.
I use the image file to flash to the SD card, but you could also install the Docker DEB file (software package) onto your Raspbian OS. This will be set up for the ARM hardware the Pi runs.
Setting the Hostname
Once we have flashed the image to the SD card and run through the first boot, which automatically will resize the root file size to use all of the available storage, we are ready to set the hostname. This is a little different in the HypriotOS. Their boot-loader initializes the hostname from the configuration found in the /boot partition. This partition is always FAT32 allowing the hostname to be configured from another system, even from Windows, just set it before you flash the SD Card. As my system is up and running we can configure this by editing the /boot/occidentalis.txt file and changing the hostname from the default of black-pearl to your chosen hostname. A reboot will then configure both the hostname and add entries to the file: /etc/hosts.
Docker is Pre-Installed
On the image that I downloaded, which is not the most recent, Docker 1.6 was pre-installed. We cannot get much simpler than this with an RPI Docker Host out of the box. Whilst 1.8 is the latest version of Docker and available in the latest version of Hypriot; 1.6 is not old and is better than many current distributions use. The standard user Pi is configured as a member of the Docker group. This means that you do need to elevate your privileges to manage Docker. It is a feature of Docker that any member of the Docker group can manage the Docker host. The password for the user Pi is raspberry and the root password is hypriot.
We can display the version of docker we are using from the command line. The $ prompt indicating that we are logged in as the standard use, Pi.
$ docker -v
We can use the Docker client to access the Docker Host. Docker is written in Google’s GoLang. To display more detailed version information – including the client, server and GoLang – we can use the following command:
$ docker version
The screenshot follows:
If that is not enough we can become even more verbose and print out versioning information and details of the images and containers that host maintains. The command for this is as follows:
$ docker info
What is Docker?
Docker is a container virtualization product. Allowing quick and easy deployment of services contained within separated Micro-Operating Systems that share the host kernel. The downloaded images are very small and customizable. If you want a web-server or MySQL server you can spin up a container in seconds and the service will be running.
We will now fire up a web-server in its own Micro-OS and IP Address. The network is protected, being hidden behind a NAT interface on the Docker host. To fire up a container on the Docker Host we use the docker run command. Using the NAT router running on the Host interface we will run some port mappings; in this case mapping port 80 on the host to 80 within the container. As we don’t have any stored images currently, docker run will download an image and spin-up the container with the one command:
$ docker run -d -p 80:80 hypriot/rpi-busybox-httpd
The downloaded image is stored on the host for use with later containers. The whole process literally takes a few seconds and then we can browser to the Docker Host and see the website. Sure the content is not our own, but it is easy to add content to the container as it starts. The image is heavily optimized for the Pi and just a few megabytes in size. Other images that offer more customization may be larger in size, but in general will be 100MB to 200MB in size. The one image can be used to serve many containers and utilizes CoWtechnology so only the elements that are changed will need additional storage.
Creating Docker Custom Images on the Raspberry Pi
So perhaps the simple BusyBox HTTP image isn’t really floating your boat; we do not need to stop with this. Far from it. To convince you we will build a custom image based on a Debian hosted Apache Web and PHP Server. We will stick with the Raspberry Pi 2 as the Docker. As this is based on ARM hardware we will use the Armbuild/Debianimage as the base for the custom build.
Select Your Base Image
In Docker, images are Read-Only templates that can be used to provision Containers. Containers and vaguely comparable to Virtual Machines in other technologies, but very vaguely. You may also want to draw a comparison with Microsoft’s App-V from the Microsoft Desktop Optimization Pack, but instead of virtualising the Application, Docker virtualises the service instance.
One major way that Docker Containers differ from traditional virtual machines is that they are designed to run a single process. This may be your web server, or your database server or whatever. Containers have a thin read-write layer that overlays upon the underlying image from which it was provisioned. In our scenario we want to deploy an Apache HTTPD Server with PHP. We will use a Debian base image for this and during the customization we will add the required packages to the base image to create the new Docker image. To download the base image for the Pi we can use the following command:
$ docker pull armbuild/debian:8.0
Create the Dockerfile
A Docker file is a text file that contains instructions on how to build the new image. The name of the file is mandated as Dockerfile and, of course, is case-sensitive. In a perfect world you will create the file in its own empty directory as contents from the directory where the Dockerfile is located in can be added to the image you are building.
For the purpose of this we will create a new test directory in our HOME directory:
$ mkdir $HOME/test ; cd $HOME/test
From within the new directory we can create the $HOME/test/Dockerfile with the editor of choice. The contents will be similar to the following:
RUN apt-get update && apt-get install php5 && apt-get clean
To detail and annotate what we have created let’s run though the file line by line:
This instruction defines the image that we base the new image upon.
These are instructions will run inside the temporary container during image creation. We have combined the commands together to reduce the amount of layers that are created in the resulting image. Each instruction in the Dockerfile creates a new image layer. Installing PHP5on the Debian image will also install the Apache HTTPD package as a dependency.
We tell the resulting container that is booted from this image to listen on port 80 or to open port 80 to the NAT network that it is connected to. We need this to talk to the web server. You may also want to EXPOSEport 443. We will later map port 80 on the host to port 80 on the Docker container to allow access from external hosts. Although we are using the same port number, there is no need to map the same port number on the host to the container’s port.
This defines the command that will be PID 1, or Process ID 1, when the container starts. We can use CMD or ENTRYPOINT, but CMD allows us to overwrite the command from the command line, whereas ENTRYPOINT does not. This is useful sometimes in faulting a container. We would be able to start it with a base shell when ENTRYPOINT is not defined. In this instance PID 1 on the resulting container will be the Apache executable.
Create the Docker Custom Image
Now that we are in proud possession of the Dockerfile, we can build the new image. From the test directory (this is important) we can execute the following command – note the period at the end of the line is part of the code:
$ cd $HOME/test $ docker build -t debian/web .
We use the -t option to set the tag or name of the image. As it is based on Debian we can include this in the name along with /web as it is a web server image. These names are fine so long as you do not intend to upload them to Docker Hub. If uploading to the Hub they will need to be named after your Docker userid. The dot or period at the end denotes that we look for the Dockerfile in the current directory. When we run the command it may take a few minutes installing the software. From the following command we will now be able to view the images we have on the system. This will include the Armbuild/Debian 8.0 image, as well as the new Debian/web image.
$ docker images
From the demonstration Pi we are using the output show as in the following screenshot:
Using the docker run command we can soon test to see that the system works:
$ docker run -d -p 80:80 –name test debian/web
We should now be able to browse to the Docker host on port 80 and see the standard Debian welcome page. To add our own content we need to ensure the website is available in a directory, such as $HOME/www. We will first stop the test container. We can then start a new instance with the $HOME/www directory on the host Pi mapped to the directory /var/www/html/ within the container. Remember we must create the website on the Docker Host and mount it to the container during runtime.
$ docker stop test
$ docker rm test
$ docker run -d -p 80:80 -v /home/pi/www:/var/www/html \
–name test debian/web
When browsing to the site now we have access to a PHP quiz engine I created for the site: