5.6 KiB
title | date | aliases | authors | tags | resources | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Run an ARM32 Docker daemon on ARM64 servers | 2020-09-24T10:30:00+02:00 |
|
|
|
|
In the last days I worked on a suitable setup for a Drone CI 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:
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:
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.
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 >}}