I’m trying to find out about the multi-arch support of the Docker registry, and so far I’ve found things like resin/rpi-raspbian and so forth.
I’m a little uncertain about what Docker does and does not support by multi-architecture; rather than probe around, I’ve decided the most productive way to approach the topic is to assume the support is terrible or non-existent, and discuss how to implement an ideal registry to find out how close Docker is to this.
Ideally, Docker should “just work”. A
docker pull redis:3-alpine should provide the expected result on x86-64 or ARM, for example. By that logic, whatever
FROM should also just work, and should build from the same
The simplest way to achieve this, on the registry side, is to have Docker try to
docker pull from the correct architecture on the registry. If there’s an
x86-64/debian:jessie, it works; if you’re on a Raspberry Pi and it tries to pull
arm6/debian:jessie, it doesn’t.
On the build end, it’s a little more complex.
Obviously, the above implies that builds just work, so long as you have the right containers available: if your
FROM java:jre9, and that builds
FROM debian:jessie, and there is a
debian:jessie image on x86-64 and arm6, then your
Dockerfile probably builds just fine. That’s the easy part: Docker pulls the appropriate architecture, so the correct base image comes down in all cases.
The first portion of multi-arch building would be conditional builds and architecture tagging.
Dockerfile as such:
# debian:jessie FROM scratch # Unpack Debian x86-64 architecture base IFARCH x86-64 ADD rootfs-x64.tar.xz ENDIFARCH # Unpack the Raspberry Pi base if it's any of these four archs IFARCH arm7 arm8 arm8.1 rpi ADD rootfs-rpi.tar.xz # This image is compatible with any of these architectures, # and does not get built or stored separately for them all TAGARCH arm7 arm8 arm8.1 rpi ENDIFARCH RUN \ export DEBCONF_FRONTEND=noninteractive \ && apt-get update \ && apt-get upgrade \ && apt-get clean \ && env -i \ && find /var/lib/apt/lists -type f -delete CMD ["/bin/bash"]
Dockerfile as above would simply select the correct
rootfs-$ARCH.tar.xz to unpack. For multiple compatible architectures, it will also tag itself as being for those several architectures.
This has a major backwards-compatibility advantage: any existing
Dockerfile built on a given architecture will just run as-is and tag itself with the current architecture. It will either build or fail; and if it fails, it won’t produce an image. That means nothing breaks.
At the same time, architecture-specific actions such as installing a precompiled binary can occur based on the architecture. This requires modification to the
Dockerfile; and that’s a trivial modification, likely by encircling single-actions in a conditional block.
Further, to avoid clutter, we could tag things to run on multiple architectures, such that forward-compatible builds are allowed. This might be better handled by the hub preferring a more-specific build (armv8.1) over a compatible one (armv8); I’m not sure.
Engineering for multi-architecture should be relatively straight-forward. I haven’t found documentation yet explaining how this works currently, at least not in any way I’ve been able to understand. What’s clear so far is it doesn’t “just work”, as we don’t have a repository built for multiple architectures–notably the Raspberry Pi–and there are entries in the Hub specifically for Pi, rather than just “This is Debian” and it gives you the correct image if you ask for