174 lines
5.6 KiB
Markdown
174 lines
5.6 KiB
Markdown
|
---
|
||
|
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.
|
||
|
|
||
|
<!--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 -->
|