Like many other developers, I have to work with computers with different processor architectures. For me it’s amd64 (x86_64) on the laptop and arm64 (aarch64) on the server. For some it may be the other way around. Fortunately I mostly write Go, which makes cross-compilation quite easy. Docker adds some extra steps, but is very nice for deploying software.
matrix-login was originally deployed on the same architecture where it was written. But then I wanted to deploy it on an arm64 server.
Go is fairly easy to cross-compile. You need to add the environment variables
GOOS and GOARCH when building:
GOOS=linux GOARCH=arm64 go build ...
Docker needs to be told what to run of the build platform and what to run on the target platform:
FROM --platform=$BUILDPLATFORM golang:latest AS build
ARG TARGETOS TARGETARCH
RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build
FROM --platform=$TARGETPLATFORM scratch
COPY --from=build /binary /binary
I prefer producing Go binaries with CGO disabled and delivered on docker images from scratch in order to minimize image size and avoid hidden dependencies.
Building is done using docker buildx:
docker buildx create --use # need a builder, only once
docker buildx build --platform linux/arm64,linux/amd64 -t docker.io/ptman/test --push .
That’s really all there is to it, but you can check out the more complete example on GitLab