You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
build(docker): cross-compile the musl build instead of emulating it
The scratch runtime as first written dropped the --platform pin from the musl
builder, so arm64 compiled under QEMU. I estimated 20-45 minutes for that by
extrapolating from Nexus, which builds the same way. Nexus's tree is far
smaller; ours ran 6h42m and was killed still compiling. The estimate was
presented as informed and was not — it should have been "I have not measured
this".
Cross-compiled with cargo-zigbuild the same build takes 10 minutes for both
architectures. Both numbers are now in the Dockerfile so nobody repeats the
emulation thinking it is equivalent.
zig rather than clang because Rust links musl targets with rustup's own
self-contained CRT, so pure-Rust code cross-compiles unaided — the gap is
aws-lc-sys and zstd-sys, which are C. `xx-info triple` resolves musl targets to
-linux-gnu, and clang against Debian's arm64 musl sysroot fails on a missing
crtend.o. `zig cc` ships a complete cross toolchain, which is exactly what was
missing.
Three failures on the way, each fixed rather than worked around:
- The toolchain shared a stage with the compile, so when crates.io served 503s
mid-fetch the whole thing restarted. It is now its own stage, and
cargo-zigbuild arrives as the project's prebuilt binary instead of
`cargo install --locked`, which compiled a tool from source on the critical
path of every build. That stage now takes 20 seconds.
- Both architectures shared the cargo registry cache mount without a sharing
mode, so they raced unpacking into the same directory and died with
"failed to unpack cfg-if: File exists". Now `sharing=locked`.
- The static-link gate was written `... || { echo "not statically linked"; }`,
which catches every failure in the chain. When the compile failed the binary
never existed, and the gate still blamed linkage — a check reporting the
wrong cause with confidence. Now an `if !` around only what it tests.
Also pins pnpm. The dashboard stage installed `pnpm@latest` over node:20, and
pnpm's latest started requiring Node >= 22.13 (it imports node:sqlite), so the
build broke with ERR_UNKNOWN_BUILTIN_MODULE. Nothing here changed; the outside
world did. Every workflow already pinned pnpm@10 and dashboard/package.json
declares packageManager pnpm@10.15.1 — the Dockerfile was the one place still
floating.
Published and verified: 3.7.1 and 3.7.1-fastembed, both amd64+arm64. The
default image scans 0 packages / 0 vulnerabilities and boots healthy from the
registry; the arm64 fastembed binary runs (`vectorizer 3.7.1`), which is the
check 3.6.0 failed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
0 commit comments