--- title: "Run an ARM32 Docker daemon on ARM64 servers" date: 2020-09-24T10:30:00+02:00 authors: - robert-kaussow tags: - Automation - Container - Sysadmin resources: - name: feature src: "images/feature.jpg" params: anchor: Center credits: > [Yannick Pipke](https://unsplash.com/@joker2000) on [Unsplash](https://unsplash.com/s/photos/cpu) --- In the last days I worked on a suitable setup for a [Drone CI](https://drone.io/) server to support multi-arch builds. While the setup for common x86 Drone runners is easy, working with setups for ARM, especially ARM32, is a bit tricky. The easiest way would be to have native servers of the respective architecture available. However, it's difficult to find hosting offers for ARM at all - for ARM32 this seems almost impossible. I decided to use Amazon EC2 ARM64 servers, they are relatively cheap and can also be used as a private customer. But how do you turn an ARM64 server into an ARM32 server? Basic requirement is an ARMv8 CPU. This type supports (in most cases) both `AArch32` and `AArch64`. The first step is to enable multi-arch support on your operating system. I use Ubuntu 18.10 for this setup: ```Shell dpkg --add-architecture armhf ``` Then add the Docker CE repository for ARM32 and install the packages: {{< highlight bash "linenos=table" >}} # add GPG key curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - # add repos add-apt-repository \ "deb [arch=armhf] https://download.docker.com/linux/ubuntu \ $RELEASE \ stable # install apt-get update apt-get install docker-ce:armhf {{< /highlight >}} To use the right architecture within Docker containers you still have to force the Docker daemon into ARM32 mode. This can be accomplished by two systemd overwrites: {{< highlight bash "linenos=table" >}} # overwrite docker.service # /etc/systemd/system/docker.service.d/override.conf [Service] ExecStart= ExecStart=/usr/bin/setarch linux32 -B /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock # overwrite containerd.service # /etc/systemd/system/containerd.service.d/override.conf [Service] ExecStart= ExecStart=/usr/bin/setarch linux32 -B /usr/bin/containerd {{< /highlight >}} That's it. Don't forget to reload and restart the systemd daemon: ```Shell systemctl, daemon reload systemctl, restart, docker ``` What you get is a Docker daemon that runs in ARM32 mode. This can be used for example to start a Golang container and build apps without cross-compile. {{< highlight bash "linenos=table" >}} root@ip-10-0-225-151:~# docker version Client: Docker Engine - Community Version: 19.03.13 API version: 1.40 Go version: go1.13.15 Git commit: 4484c46 Built: Wed Sep 16 17:07:23 2020 OS/Arch: linux/arm Experimental: false Server: Docker Engine - Community Engine: Version: 19.03.13 API version: 1.40 (minimum version 1.12) Go version: go1.13.15 Git commit: 4484c46 Built: Wed Sep 16 17:01:08 2020 OS/Arch: linux/arm Experimental: false containerd: Version: 1.3.7 GitCommit: 8fba4e9a7d01810a393d5d25a3621dc101981175 runc: Version: 1.0.0-rc10 GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd docker-init: Version: 0.18.0 GitCommit: fec3683 root@ip-10-0-225-151:~# docker run alpine uname -a Linux dbad5ddeb5ea 5.3.0-1035-aws #37-Ubuntu SMP Sun Sep 6 01:17:41 UTC 2020 armv8l Linux {{< /highlight >}} Just a word of warning. I'm not a hardware specialist and there might be some situations where this setup does not work. Furthermore it seems that some operating systems have problems to recognize `armv8l` as ARM32 architecture. For OpenSuse as an example I had to force `zypper` into `armv7hl` mode to get it working. After this step building ARM32 OpenSuse Docker images also works for me. ```Shell sed -i 's/# arch = s390/arch = armv7hl/g' /etc/zypp/zypp.conf ``` If you want to give it a try, I've prepared a minimal Cloud-Init configuration: {{< highlight yaml "linenos=table" >}} #cloud-config apt_reboot_if_required: false package_update: true package_upgrade: true bootcmd: - [ dpkg, --add-architecture, armhf ] apt: sources: docker.list: source: deb [arch=armhf] https://download.docker.com/linux/ubuntu $RELEASE stable keyid: 0EBFCD88 packages: - 'docker-ce:armhf' write_files: - path: /etc/systemd/system/docker.service.d/override.conf content: | [Service] ExecStart= ExecStart=/usr/bin/setarch linux32 -B /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock - path: /etc/systemd/system/containerd.service.d/override.conf content: | [Service] ExecStart= ExecStart=/usr/bin/setarch linux32 -B /usr/bin/containerd runcmd: - [ systemctl, daemon-reload ] - [ systemctl, restart, docker ] {{< /highlight >}}