feat(ci): publish the image for linux/arm64 as well - #25
Conversation
There was a problem hiding this comment.
Cross-compile setup looks correct: --platform=$BUILDPLATFORM keeps the builder native, TARGETARCH drives the target triple/linker, and the export of CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER persists within the same RUN shell so it's visible to the later cargo build. Runtime stage correctly stays unpinned so it resolves per-target-platform. README numbers match the stated current release (0.4.0/0.4).
Nit: the arm64 apt-get update/install runs on every build with no version pin on gcc-aarch64-linux-gnu/libc6-dev-arm64-cross — fine for now, just a minor future reproducibility gap.
No blocking issues. The one real unknown (multi-platform smoke test behavior) is already called out in the PR description with a sane mitigation (re-run on failure).
Closes #3.
Most of that issue landed with the release wiring in #17: the image publishes on release, carries the version, the
major.minorline andlatest, gets a Trivy scan, a cosign signature, a provenance attestation and a CycloneDX SBOM, and has to answer/healthbefore the push is allowed.0.2.0,0.3.0and0.4.0are on GHCR with their signatures. What was left is the architecture.arm64 without emulation
The naive way to get a second architecture is to hand qemu to the runner and let the whole build run emulated. For a Rust project that is brutal — the compiler itself runs under emulation, and a two-minute build becomes twenty.
So the builder stage is pinned to
--platform=$BUILDPLATFORMand cross-compiles instead: it stays native, adds the target and the cross linker, and produces the aarch64 binary at full speed. The runtime stage is the only thing that varies per architecture, and it does nothing butCOPY. No qemu, no binfmt on the runner, no emulated compiler.That is also why passing two platforms to the org reusable is safe here despite its note about needing binfmt: nothing in this Dockerfile ever executes a target-architecture binary at build time.
Verified locally, not assumed
docker buildx build --platform linux/amd64,linux/arm64produces the manifest list. The arm64 image reportsarm64/linux, and running it under emulation it starts asnonroot, creates its storage root and answers/health— which also re-confirms the directory ownership fix from #17 on the other architecture.One thing the cross build needed and did not have:
libc6-dev-arm64-cross.gcc-aarch64-linux-gnuonly recommends it, and the image installs with--no-install-recommends, soringfailed to compile its C sources against missing target headers. Found by building it rather than by reading the Dockerfile.On the
majortagThe issue asks for a floating major tag. Under
zeroverthat tag would be0, spanning every0.x— and0.xminor bumps are exactly where breaking changes live, so:0would promise compatibility the versioning explicitly refuses. The floating line stays0.4until1.0.0, and the major tag makes sense from that day.What is not verified
docker.ymlonly fires on a published release, so this cannot run in the PR. The one interaction I could not exercise is the reusable's smoke test against a two-platform build: it runspodman runon the local manifest list, which resolves to the host architecture. If it turns out otherwise the release publishes nothing and is fixed by re-running the workflow, since the push happens after the smoke test, not before.