Docker Cross-compilation
Date: 2018/03/14
Context
Most desktop computers, and our Travis automated build agents have the x86_64 CPU architecture. Raspberry Pi has an ARMv7 architecture, and can't run Docker images built on x86_64.
Compilation of Brewblox service images is currently done manually on a Pi, and takes inordinately long (1 hour for history service). We'd rather do this on the Travis build agent we're also using for creating the x86_64 container images.
Requirements
- Automated building of ARMv7 architecture service images, integrated with the existing CI pipeline
- Quick building of images (<5 minutes)
Existing
The following docker-compose snippet is valid for both x86 and ARM architectures:
services:
eventbus:
image: rabbitmq:alpine
Inspection of the Docker hub registry shows that this is done using manifests. (more info)
The RabbitMQ image rabbitmq:alpine
does not directly exist. Instead, it is an image with multiple manifests: one for each architecture.
Pulling the rabbitmq:alpine
image while on a Raspberry Pi will actually pull the arm32v7/rabbitmq:alpine
image.
Of note is that manifests are still considered an experimental feature - you need to explicitly enable support.
If you're ok with using a different tag for a different architecture (latest
vs rpi-latest
) manifests are not required.
Building
Hypriot (the team responsible for many Docker images for the Pi), published a blog post detailing the feasibility of building ARM containers in Travis.
When building the below Dockerfile, this did not work as hoped. While QEMU supports compilation, the host architecture is still x86_64. The image build was ok - but did not produce ARM binaries.
FROM python:3.6
EXPOSE 5000
RUN pip3 install -U brewblox-service
ENTRYPOINT ["python3", "-m", "brewblox_service"]
Explicitly pulling the arm image did not work either.
FROM arm32v7/python:3.6
...
Sending build context to Docker daemon 17.92kB
Step 1/6 : FROM arm32v7/python:3.6
3.6: Pulling from arm32v7/python
no matching manifest for linux/amd64 in the manifest list entries
The assumption is that for Hypriot's solution to work, we'd need a non-manifest ARM base image.
Issues
Some googling revealed our issues to be an exact duplicate of an open issue - down to the scenario being attempted Python3 builds on a Travis agent. The issue is fresh (last post 8 feb 2018).
This revealed that there is no current override allowing docker to pull an image not matching the host architecture.
Conclusion
Cross-architecture image building is probably on Docker's horizon, but is not currently supported. There are some workarounds, but those do not play nice with Docker multi-arch manifests.
Our problem will be solved as soon as Docker supports the hypothetical --arch=arm32v7
when pulling images.
Decisions:
- Build ARM Docker images on a Raspberry Pi until Docker supports cross-architecture pulling.
- Future task: run a build agent on a Raspberry, shadowing the Travis agent, but on ARM.