thegeeklab/content/posts/2020/run-arm32-docker-daemon-on-arm64-servers/index.md

176 lines
5.6 KiB
Markdown
Raw Normal View History

2020-09-24 08:38:27 +00:00
---
title: "Run an ARM32 Docker daemon on ARM64 servers"
date: 2020-09-24T10:30:00+02:00
2022-03-13 10:57:09 +00:00
aliases:
2022-03-13 11:04:30 +00:00
- /run-arm32-docker-daemon-on-arm64-servers/
2020-09-24 08:38:27 +00: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.
<!--more-->
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:
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<!-- spellchecker-disable -->
{{< 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 >}}
<!-- spellchecker-enable -->
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
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:
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<!-- spellchecker-disable -->
{{< 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 >}}
<!-- spellchecker-enable -->
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
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.
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<!-- spellchecker-disable -->
{{< 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 >}}
<!-- spellchecker-enable -->
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
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:
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<!-- spellchecker-disable -->
{{< 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 >}}
<!-- spellchecker-enable -->
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->