Bug
The builder stage in mcp/Dockerfile uses --platform=$BUILDPLATFORM:
FROM --platform=$BUILDPLATFORM cgr.dev/chainguard/wolfi-base:latest AS builder
This causes native Node.js modules (specifically better-sqlite3, which includes a C extension compiled via node-gyp) to be compiled for the build machine's architecture rather than the target architecture.
Impact
When building on an arm64 machine (e.g., Apple Silicon Mac) targeting amd64 (e.g., a standard Kubernetes cluster), the resulting image contains arm64 .node binaries that cannot execute on amd64 nodes. The pod crashes with:
exec /usr/bin/node: exec format error
or at runtime:
Error: /app/node_modules/better-sqlite3/build/Release/better_sqlite3.node: cannot open shared object file
Root Cause
$BUILDPLATFORM tells Docker to run the builder stage natively on the build machine's architecture for speed. This is correct for pure-JS builds, but better-sqlite3 uses node-gyp to compile a C extension. When the builder runs as arm64, node-gyp produces an arm64 binary — which is then copied into the final amd64 image and fails.
Fix
Change the builder stage to use $TARGETPLATFORM:
FROM --platform=$TARGETPLATFORM cgr.dev/chainguard/wolfi-base:latest AS builder
This ensures native modules are compiled for the correct target architecture. The tradeoff is that on cross-architecture builds, the builder stage runs under QEMU emulation (slower), but produces correct binaries.
Why this hasn't been caught
If your CI/CD builds on amd64 and deploys to amd64, $BUILDPLATFORM == $TARGETPLATFORM and the bug is invisible. It only manifests when cross-compiling (e.g., arm64 Mac → amd64 cluster).
Bug
The builder stage in
mcp/Dockerfileuses--platform=$BUILDPLATFORM:FROM --platform=$BUILDPLATFORM cgr.dev/chainguard/wolfi-base:latest AS builderThis causes native Node.js modules (specifically
better-sqlite3, which includes a C extension compiled vianode-gyp) to be compiled for the build machine's architecture rather than the target architecture.Impact
When building on an arm64 machine (e.g., Apple Silicon Mac) targeting amd64 (e.g., a standard Kubernetes cluster), the resulting image contains arm64
.nodebinaries that cannot execute on amd64 nodes. The pod crashes with:or at runtime:
Root Cause
$BUILDPLATFORMtells Docker to run the builder stage natively on the build machine's architecture for speed. This is correct for pure-JS builds, butbetter-sqlite3usesnode-gypto compile a C extension. When the builder runs as arm64,node-gypproduces an arm64 binary — which is then copied into the final amd64 image and fails.Fix
Change the builder stage to use
$TARGETPLATFORM:FROM --platform=$TARGETPLATFORM cgr.dev/chainguard/wolfi-base:latest AS builderThis ensures native modules are compiled for the correct target architecture. The tradeoff is that on cross-architecture builds, the builder stage runs under QEMU emulation (slower), but produces correct binaries.
Why this hasn't been caught
If your CI/CD builds on amd64 and deploys to amd64,
$BUILDPLATFORM==$TARGETPLATFORMand the bug is invisible. It only manifests when cross-compiling (e.g., arm64 Mac → amd64 cluster).