Docking Containers



Virtualisation is cool. Most of this site, so far, seems dedicated to it in some way so far!

Up until this point, I have mainly focussed playing with Microsoft's Hyper-V (mainly in Windows 10 Pro), QEMU+KVM and a little dabble in to VMware's ESXi and Kubernetes.

Recently though, my daughter decided that she wanted to a keep a blog site about her adventuers in training our puppy. I therefore wanted to set up something that was relatively quick and easy for me to maintain and for her to use. With this in mind, I had thought initially that I would just add a subsite to my own, but I really couldn't be bothered trying to figure out how to route subsites on an Apache HTTP server so I settled on using something that I was already familiar with - Hugo (which I use to render this site) and I figured that I would go ahead and virtualise this. I felt that creating a new VM on my QEMU+KVM system would be a bit wasteful and decided to turn my Raspberry Pi in to a containiner host. The technology that I chose for this is Docker. I chose this mainly due to some previous small scale investigations in to the tech (along with Kubernetes) - but this investigation was short lived as I didn't really have a solid, pratical application for the technology and now I do.

Steps to set up the Docker environment

With this in mind, I took the following steps:

  1. Wiped my Raspberry Pi SD card and imaged it with Debian Buster. Couple of things to note about the Debian Pi image
    • There is only a root account which has no password (so no remote login intially).
    • The default login shell is /bin/sh - this caught me out for a long time during my intial setting up phase as commands I was expecting to work did not as they required Bash.

    Error received along the lines of failed to run command '/bin/sh: Exec format error'

  2. Connected to a monitor, added my user (and ensured /bin/bash was set as the login shell!), ensured the base install was updated, installed sudo, docker and hugo.
    • useradd -ms /bin/bash toro - this adds a user called 'toro', adds /home/toro and sets the login shell to /bin/bash
    • passwd toro - allows you to set the password for 'toro' which then allows remote login (via SSH etc).
    • apt update && apt upgrade - update apt and then upgrade any packages
    • apt install sudo docker hugo -y - installs sudo, docker, hugo and and accepts the 'are you sure' prompt automatically
    • usermod -aG sudo toro - adds user 'toro' to the 'sudo' group
    • usermod -aG docker toro - adds user 'toro' to the 'docker' group allowing toro to run docker commands without the need for sudo.
  3. Next I ensured that the SSH server was running by using systemctl status ssh and confirmed that I was able to login remotely (IP address was assigned by DHCP and used ip a to confirm the configured IP). Once this was confirmed, logged out and disconnected the monitor.

    I have now reserved the IP in my DHCP server (Pi-Hole) so that the IP does not get re-assigned.

  4. Rebooted the Pi to ensure that all updates were in place and running - though not strictly necessary.
  5. Confirmed that Docker is working by executing `docker run hello-world'

Customising Docker image

Now happy that docker was up and running. I set about trying to figure out how to create my own image which had hugo baked in as I would use this as the web server within the container. There were lots of trials and lots of failures. But over the course of a few hours (spread over a few days) I managed to crack it and it seems so simple now!

I was not too worried about the base image that I used, however Apline Linux seemed like a popular choice as it so so stripped down compared to the alernatives like Ubuntu, Debian or Arch etc. At the time of writing the only real difference was the package manager, apk (which you can read about here). I certainly wasn't worried about a new package manager, on the surface the provide the exact same features as another one and I experience on using 'yum', 'apt', 'pacman' and a few others.

So the first thing I had to do was to set up my 'Dockerfile' in order to set up my image. The file that I ended up with after many, many attempts looks like this:

 1#Use the Apline image
 2FROM alpine
 4#Set the maintainer name, not required
 7#Set environment variables for use during the image building operation
 8ENV HUGO_SITE=/srv/hugo \
 9    HUGO_BASEURL=/ \
10    HUGO_SOURCEDIR=site_source
12# Run commands, in this case hugo and then make a directory based on the HUGO_SITE variable
13RUN apk --no-cache add hugo && mkdir -p ${HUGO_SITE}
15# Set the working directory whilst working inside the container
18# Define a volume to use
21# Expose container port (in this case the default port for hugo server
22EXPOSE 1313
24# Copy the site source files from the host to the conainer
27# Finally, run the hugo server and leave it running (if nothing is running, the conainer will immediately shut down)
28CMD hugo server \
29	--bind \
30	--navigateToChanged \
31	--templateMetrics \
32	--buildDrafts \
33	--baseURL ${HUGO_BASEURL} \
34	--appendPort=false \
35	--minify \
36	--disableLiveReload \
37	--gc