diff --git a/.dictionary b/.dictionary index ae63b91..4bf6381 100644 --- a/.dictionary +++ b/.dictionary @@ -26,3 +26,12 @@ IPS eBay Aliexpress retrosix +ARM32 +ARM64 +ARMv8 +Cloud-Init +EC2 +OpenSuse +x86 +systemd +Golang diff --git a/content/posts/run-arm32-docker-daemon-on-arm64-servers/images/feature.jpg b/content/posts/run-arm32-docker-daemon-on-arm64-servers/images/feature.jpg new file mode 100644 index 0000000..e54b862 Binary files /dev/null and b/content/posts/run-arm32-docker-daemon-on-arm64-servers/images/feature.jpg differ diff --git a/content/posts/run-arm32-docker-daemon-on-arm64-servers/index.md b/content/posts/run-arm32-docker-daemon-on-arm64-servers/index.md new file mode 100644 index 0000000..5ab9e22 --- /dev/null +++ b/content/posts/run-arm32-docker-daemon-on-arm64-servers/index.md @@ -0,0 +1,173 @@ +--- +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 >}} + + +