Docker Alpine Linux Image for ARM

May 25, 2015

linux

Alpine Linux is a super small Linux distribution which targets Docker. The only downside is that they use musl libc instead of glibc, which causes some issues for Golang programs. But I want this as a base image for SkyDNS on my Raspberry Pi, running HypriotOS.

After reading a modest amount of documentation I found the mkimage-alpine.sh script which build a docker image ala alpine, but makes it possible to select different archs. I had to tweak this script a little to make it do what I want, but after that it worked.

--- mkimage-alpine.sh.1 2015-05-25 14:47:09.415635082 +0100
+++ mkimage-alpine.sh   2015-05-25 14:38:02.815659184 +0100
@@ -2,13 +2,8 @@

 set -e

-[ $(id -u) -eq 0 ] || {
-   printf >&2 '%s requires root\n' "$0"
-   exit 1
-}
-
 usage() {
-   printf >&2 '%s: [-r release] [-m mirror] [-s]\n' "$0"
+   printf >&2 '%s: [-r release] [-m mirror] [-a armhf|x86|x86_64] [-s]\n' "$0"
        exit 1
 }

@@ -20,7 +15,7 @@

 apkv() {
        curl -s $REPO/$ARCH/APKINDEX.tar.gz | tar -Oxz |
-       grep '^P:apk-tools-static$' -A1 | tail -n1 | cut -d: -f2
+       grep -a '^P:apk-tools-static$' -A1 | tail -n1 | cut -d: -f2
 }

 getapk() {
@@ -51,7 +46,8 @@
        tar --numeric-owner -C $ROOTFS -c . | xz > rootfs.tar.xz
 }

-while getopts "hr:m:s" opt; do
+ARCH=$(uname -m)
+while getopts "ha:r:m:s" opt; do
        case $opt in
                r)
                        REL=$OPTARG
@@ -62,6 +58,8 @@
                s)
                        SAVE=1
                        ;;
+                a)      ARCH=$OPTARG
+                        ;;
                *)
                        usage
                        ;;
@@ -72,7 +70,7 @@
 MIRROR=${MIRROR:-http://nl.alpinelinux.org/alpine}
 SAVE=${SAVE:-0}
 REPO=$MIRROR/$REL/main
-ARCH=$(uname -m)
+ARCH=armhf

 tmp
 getapk

Copy this script to your Pi and run it. It should create an image that you can use as a base image. All docker images that I create for ARM (or non x86_64) will be postfixed with the arch. So this will be named miek/alpine-armv6l (uname -m on the Pi).

Next we cross compile SkyDNS for my PI: GOARCH=arm GOARM=5 go build This creates a static binary.

Note that creating a static binary for x86 requires: go build -ldflags "-linkmode external -extldflags -static"

Then we tweak the Dockerfile a little (a different FROM line) and create an image for the Raspberry. This all needs to be done on the Pi itself. docker build -t miek/skydns-armv6l .

End result:

Proof:

$ docker run miek/skydns-armv6l
2015/05/25 14:23:24 skydns: falling back to default configuration, could not read from etcd: 501: All the given peers are not reachable (Tried to connect to each peer twice and failed) [0]
2015/05/25 14:23:24 skydns: ready for queries on skydns.local. for tcp://127.0.0.1:53 [rcache 0]
2015/05/25 14:23:24 skydns: ready for queries on skydns.local. for udp://127.0.0.1:53 [rcache 0]

Yes, no Etcd, because of this.

Docker  ARM