qemu-static allows you to run containers built for other architectures (of course, with a performance penalty). BUT this means you can cross-compile to arm/amd64 quite easily.
Here’s an example:
$ docker run --rm --privileged \
multiarch/qemu-user-static \
--reset -p yes
$ uname -a
Linux mindy 6.9.3-arch1-1 #1 SMP PREEMPT_DYNAMIC Fri, 31 May 2024 15:14:45 +0000 x86_64 GNU/Linux
$ cat Dockerfile
FROM --platform=${TARGETPLATFORM:-linux/amd64} alpine AS base
RUN apk add crystal
$ docker build . --platform=aarch64 -t crystal-arm
$ docker run --platform=aarch64 -ti -v .:/src -w /src crystal-arm crystal build hello.cr -o hello-arm
$ file hello-arm
hello-arm: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-aarch64.so.1, BuildID[sha1]=c10324de8eb05c5ae2729170ee8d0c53583fd7a3, with debug_info, not stripped
You can even create a couple of shell aliases for crystal and shards running in arm and it just works:
$ alias crystal-arm="docker run --platform=aarch64 -ti -v .:/src -w /src crystal-arm crystal"
$ crystal-arm build hello.cr -o hello-arm
This looks (to me) much simpler than the other solutions being discussed. I can expand it to a proper tutorial if there is interest.