Cross compile Ethereum for Docker and ARM

Supply-chain attacks are quite popular these days, as the Solarwind hack demonstrated. My advise is don’t trust blindly containers, and run sanity checks on your build environment!

Geth, the official implementation of Ethereum protocol written in Go, can be cross-compiled for different CPU architecture including ARM.

At the time of writing, the official docker image of geth is not build for ARM architecture, only linux/amd64.

We will explain here how to build your own flavour of geth container from the sources for different platforms.

Docker multi-platform to the rescue

The first part is to find a coss-compilation toolchain that can perform this task nice and sound. Luckily, Docker is multi-platform for quite some time now, and a buildx command ease the process to build for multiple platform at once!

Let’s create a cross platform compilation stack, and them try to build Geth!

First thing first, see what is the current state of the buildx setup

$ docker buildx ls

NAME/NODE           DRIVER/ENDPOINT             STATUS  PLATFORMS
default *           docker
  default           default                     running

If your output look like this, it’s ok, you have a default builder and nothing else. Let’s create one capable of cross-compiling

$ docker buildx create --use --name xplatformbuilder

And bootstrap the environment

$ docker buildx inspect --bootstrap

Great, that’s it, that was not more complicated than that.

$ docker buildx ls

Now, after a proper checkout of the Geth sources, let’s build them for multiple achitecture:

docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t ethereum/go-client:latest .

The previous command will take some time, but didn’t produce much useful result. We’ll need to push the containers to a container registry to be able to pull from multiple targets. Setting up a docker registry is beyond the scope of this article, but assuming you have one, you could tag the build accordingly and --push the image:

docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t my.docker.registry/ethereum/go-client:latest --push .

Now you can pull your freshly built Geth container from multiple targets:

Raspberry Pi 4

$ uname -m
aarch64
$ docker pull my.docker.registry/ethereum/go-client:latest

Odroid XC4

$ uname -m
armv7lv
$ docker pull my.docker.registry/ethereum/go-client:latest

Amd Epyc or Intel Xeon

$ uname -m
x86_64
$ docker pull my.docker.registry/ethereum/go-client:latest

And so on…

Enjoy running containerized Geth on ARM!

> admin.nodeInfo.name
"Geth/v1.9.25-stable-e7872729/linux-arm64/go1.15.7"

Side note, since this is now