Docker Alpine Linux Image for ARM
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:
- Alpine image: https://registry.hub.docker.com/u/miek/alpine-armv6l/
- SkyDNS image: https://registry.hub.docker.com/u/miek/skydns-armv6l/
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.