Dockerizing Linux Alpine for Raspberry Pi

Intro

Alpine Linux is an independent, non-commercial, general purpose Linux distribution designed for power users who appreciate security, simplicity and resource efficiency. In my opinion it has become very popular thanks to Docker momentum, because it has a small footprint and is optimized to be run in RAM.

There is official documentation explaining how to install Alpine Linux on a Raspberry Pi. However, I prefer to use Alpine Linux inside dockerized environments and to use Raspbian based on the popular and mature Debian Jessie as OS host on the Rasperry Pi.

I would like to document two techniques for dockerize Linux Alpine and to describe how can be used on your Raspberry Pi. With this documentation you are going to be able to ensure better resource consumptions of docker containers on your Pi.

Getting Started

Recently I wrote an article documenting how to install Raspbian and Docker in your Pi, maybe it would be helpful before you move forward with this article about dockerizing Linux Alpine.

Dockerizing techniques

Using an existing image

Docker Hub is a cloud-based registry to easily distribute and share containers. Nowadays it is very rare to not find in Docker Hub a docker image including the service you are looking for.

hypriot/rpi-alpine-scratch is one of the popular docker images you could find to create containers based on Linux Alpine in your Pi.

So this is the first technique: find existing images that contains the service(s) you need in Docker Hub portal.

To create a container from rpi-alpine-scrath, ssh login into your Pi and type this Docker sorcery:

1
sudo docker run --rm -it --entrypoint /bin/sh --name alpine1 hypriot/rpi-alpine-scratch

Previous command will:

  1. Pull to your Pi Docker engine a copy of hypriot/rpi-alpine-scratch image.
  2. Create a container based on hypriot/rpi-alpine-scratch image.
  3. Shell access into this new container (type cat /etc/issue to check Alpine version)

    1
    2
    3
    / # cat /etc/issue
    Welcome to Alpine Linux 3.2
    Kernel \r on an \m (\l)
  4. Stop and remove container after you end login session.

The size of previous image is just 4.98MB!

Building your own image

You could also build your own Alpine image version using an image builder provided by Gliderlabs Team.

To get this done (in your Pi):

1. Create the builder image

You will need a builder image to create the root filesystem of your Alpine image.

a) Clone source code from Gliderlabs
1
2
git clone https://github.com/gliderlabs/docker-alpine.git && \
cd docker-alpine/
b) the “builder” image has to be FROM a rpi based alpine
1
sed -i "/FROM/ s:.*:FROM hypriot/rpi-alpine-scratch:" builder/Dockerfile
c) build the “builder” image
1
sudo docker build -t alpine-builder builder

2. Build Alpine Linux image

Using the previous builder image you will be able to create and package the root filesystem in your own docker Alpine image.

a) Generate Alpine root filesystem
1
sudo docker run --name alpine-build-v3.6 alpine-builder -s -t UTC -r v3.6 -m http://dl-4.alpinelinux.org/alpine > ./versions/gliderlabs-3.6/rootfs.tar.xz
b) Package filesystem in your Alpine image
1
sudo docker build -t my-rpi-alpine versions/gliderlabs-3.6

3. Create a container from your new image

You have created your own blueprint!, now you can create Alpine containers in your Raspberry Pi as much as you want.

Now your image source is my-rpi-alpine and you can create containers in same way as hypriot/rpi-alpine-scratch

1
sudo docker run --rm -it --entrypoint /bin/sh --name alpine2 my-rpi-alpine

After executed the previous command you will be able to access new Alpine container and you could also type cat /etc/issue to check Alpine version

1
2
3
/ # cat /etc/issue
Welcome to Alpine Linux 3.6
Kernel \r on an \m (\l)

The size of this image is 5.06MB!

For simplicity, below you can get the full commands sequence.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash

# Clone source code from Gliderlabs
git clone https://github.com/gliderlabs/docker-alpine.git && \
cd docker-alpine/

# the builder image has to be FROM a rpi based alpine
sed -i "/FROM/ s:.*:FROM hypriot/rpi-alpine-scratch:" builder/Dockerfile

# build the builder image
sudo docker build -t alpine-builder builder

export ALPINE_VERSION="3.6"
# Generate Alpine root filesystem
sudo docker run --name alpine-build-v${ALPINE_VERSION} alpine-builder -s -t UTC -r v${ALPINE_VERSION} -m http://dl-4.alpinelinux.org/alpine > ./versions/gliderlabs-${ALPINE_VERSION
}/rootfs.tar.xz

#Package filesystem in your Alpine image
sudo docker build -t my-rpi-alpine versions/gliderlabs-${ALPINE_VERSION}

# Builded ok
echo "Successfully built. Try: sudo docker run --rm -it --entrypoint /bin/sh --name alpine2 my-rpi-alpine"

Conclusions

The process of creating docker containers is straightforward. You can create your containers from existing images in Docker Hub or from your own local Dockerfiles (to mention the two techniques I use most often).

A Raspberry-based docker image based on Debian Jessie uses 126MB of disk space and based on Alpine uses 5MB of disk space. It is clear that Raspbian is much bigger because it provides services considered essentials for standard users, Alpine has a minimalistic vision and you must choose which services are you going to include on the image. To me Alpine approach is better to be used in dockerized environments with limited resources hosts, like for instance a Raspberry Pi.

Make me happy and let me know in comments your thoughts?

Happy coding!