Some time ago, I investigated how to switch from a manual docker image generation to an automated process for armhf based dockers using public CI servers. Building on a dedicated target hardware is still preferable, but most Open Source CI systems run on an x86/amd64 host at the moment.
My first approach, running docker on an emulated armhf machine didn't run very well using a docker-in-docker / inception approach, as go and qemu interfere with each other a bit badly. Not quite sure if this changes over time, while reading the issue's comments.
Around Christmas, I've read a blog post about a build variant using qemu, where they demonstrate a way of building arm images on any x86 machine, useful if you do not have the capability to modify the kernel for binfmt support. But that approach also requires an additional binary to reside in the base image, emulating calls of the foreign architecture. Well, for now, this seems to be the way to go and it doesn't do any harm on a target platform either.
How do we get a base image with a working copy of qemu-arm?
I decided to go with armhf-debian-docker as it simply defines a Makefile wrapper around the original mkimage contributions of docker. I've applied some changes, which might find it's way upstream again if desired, but generally spoken, it uses qemu-debootstrap instead of debootstrap, to create an armhf based image. You might have already heard about Travis CI, a nice continuous integration platform, especially when it comes to Open Source projects as they offer a free service for that kind of projects. Travis CI runs the VM instance with a Linux distribution that has been configured with binfmt support, which means, that armhf architectures can be emulated without the mentioned approach from above, but it's still worth reading.
Any subsequent build of an image, that is based on an armhf parent image, needs to be configured with the following lines (the last line is the only mandatory line):
# e.g. qemu-debootstrap installs qemu-arm-static under /usr/bin/qemu-arm-static
before_script:
- sudo cat /proc/sys/fs/binfmt_misc/status
- sudo sh -c "echo ':arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-arm-static:' > /proc/sys/fs/binfmt_misc/register"
If we have multiple platforms, how do we distinguish on docker hub?
I've read from different sources, that a good citizen marks the image with a corresponding platform suffix, like owncloud-armhf, but personally, I don't like that approach as it leads to a mixed, less coherent repository where technical limitations are expressed through naming conventions. For instance, apt should work on any platform equally, and, it does well. That's what I expect from a Dockerfile too, as it can be treated as a recipe for infrastructure.
Unfortunately, a prefix-based solution with constant image names would require multiple accounts, leading to other difficulties and issues. Docker's repository shows great effort for ARM - thanks to IoT here - and the mentioned setup might change in the future, hiding the architecture's property then properly. For that reason, I decided to take the recommended suffix-based approach and to re-tag the specific image prior of building.
What about trust?
A so called Automated Build requires a Dockerfile, which will be used by docker to build the image eventually, but this is limited to the mainly supported architecture and is pretty contrary to the primary goal of building ARM images. Of course, that doesn't mean that there is no room left for transparency and as soon as I've brought up all dog-food repositories in form of automated Travis builds, I'll try to integrate the Content Trust mechanism as a further step.
Please have a look at the repository and share your thoughts. Any repository starting with docker can be taken as an example and they all share a couple of CI bash files.
Update 19.05.2016
Problems seem to have gone when using a newer version of qemu 2.5.x and one of the latest 1.5.x or 1.6.x go branch. Yay, many thanks for their effort!
Become a backer or share this article with your colleagues and friends. Any kind of interaction is appreciated.