Multi Architecture Docker Image using Cross Compilation — Part 1
In todays world, it’s very important for a product to be available for all platforms like x86, s390x, arm, ppc64le etc. We cannot expect the product team to have access to these bunch of varied platforms.
If one have access to all these platforms, they can natively build/compile the application to generate platform specific binary but what if we don’t have these target platforms ?? Don’t worry — answer to the problem is Cross Compilation.
Wikipedia defines Cross Compilation as below:
A cross compiler is a compiler capable of creating executable code for a platform other than the one on which the compiler is running. For example, a compiler that runs on a Windows 7 PC but generates code that runs on Android smartphone is a cross compiler.
Most programs/applications are compiled/built on x86 platform. These programs make assumptions about the type of machine they run on, which must match the platform in question or the program won’t work. Common assumptions include:
- Word size
- Endianness (Little Endian and Big Endian)
- Alignment
- Default signedness
In addition to above, Cross compiling as its own issues like:
- Configuration issues
- HOSTCC vs TARGETCC
- Toolchain Leaks — An improperly configured cross-compile toolchain may leak bits of the host system into the compiled programs, resulting in failures that are usually easy to detect but which can be difficult to diagnose and correct. The toolchain may #include the wrong header files, or search the wrong library paths at link time. Shared libraries often depend on other shared libraries which can also sneak in unexpected link-time references to the host system.
- Libraries — Dynamically linked programs must access the appropriate shared libraries at compile time. Shared libraries to the target system need to be added to the cross-compile toolchain so programs can link against them.
If you pull a docker image that was built for x86 and try to create container on some other platform like arm , you will receive a failure that would read Exec Format Error
The reason for the Exec Format Error is the FROM tag in the Dockerfile. When the docker image is built, it pulls the Base image indicated against the FROM keyword which is usually x86 based and hence prevents it from running on any other platform.
Let’s try to overcome this problem by building docker images for the specific platform using Cross Compilation.
We will be using Quick Emulator a.k.a QEMU.
QEMU is a free opensource software that performs hardware virtualization.It emulates the machine’s processor through dynamic binary translation and provides a set of different hardware and device models for the machine, enabling it to run a variety of Guest OS.
QEMU can also do emulation for user-level processes, allowing applications compiled for one architecture to run on another.
Let’s begin and create a docker image for various platform using QEMU.
Firstly, we need to download the QEMU libraries for the platforms we wish to cross compile. See the snippet below (we don’t have x86 mentioned since x86 will be natively built and other platforms being cross compiled) :
Next. let’s modify the Dockerfile to have a placeholder for various BASE Images and copy the downloaded QEMU static libraries into the /usr/bin.
You can see an example template here : https://github.com/imdurgadas/ubuntu-ssh/blob/master/Dockerfile.template
FROM BASEIMAGE
#If we're building for another architecture than amd64, the #CROSS_BUILD_# placeholder is removed so# e.g. CROSS_BUILD_COPY #turns into COPY
#If we're building normally, for amd64, CROSS_BUILD lines are #removed
CROSS_BUILD_COPY qemu-ARCH-static /usr/bin/
Considering above template, one will have to update the BASEIMAGE and COPY static libraries based on the platform (if not x86) and prepare platform specific docker file.
See below snippet on how we can do the same.
Once we are done with above, we are all set to perform “docker build” which will create platform specific docker image even though we are not running it on those target platform. Below snippet builds the image and then pushes the same to the docker registry.
Complete script can be found here : https://github.com/imdurgadas/ubuntu-ssh/blob/master/publish.sh
Hope you have enjoyed the same !!!
Subscribe to my newsletter
Read articles from Durgadas Kamath directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Durgadas Kamath
Durgadas Kamath
I am a Tech enthusiast, Solutions Architect, Public Speaker and passionate tech blogger. I write about Serverless, Cloud, Microservices, DevOps, Open Source and new technologies.