amd64 and arm64

Building BookNest for linux/amd64 and linux/arm64

One line changes in BookNest's Dockerfile: the base stage, and with it deps and test, runs on the build platform. runtime keeps the target's node:24-slim, whose ARM node binary it never executes during the build:

Running the dependency stages natively and building two platformsShell
sed -i '/ AS base$/s/^FROM /FROM --platform=$BUILDPLATFORM /' Dockerfile
git diff -U0 | grep '^[-+]FROM'
docker build -q --platform linux/amd64,linux/arm64 -t l3-booknest-api:1.2 . >/dev/null
docker image ls --tree l3-booknest-api:1.2
docker create --name l3-arm --platform linux/arm64 l3-booknest-api:1.2 >/dev/null
docker cp -q l3-arm:/usr/local/bin/node ../node-arm64 && docker rm l3-arm >/dev/null
file -b ../node-arm64 | cut -c1-38
docker run --rm --platform linux/arm64 l3-booknest-api:1.2 node -v
Output
-FROM ${NODE_IMAGE} AS base
+FROM --platform=$BUILDPLATFORM ${NODE_IMAGE} AS base
IMAGE                 ID             DISK USAGE   CONTENT SIZE   EXTRA
l3-booknest-api:1.2   30c234b9b35a        418MB          163MB
├─ linux/amd64        ae530fb8e689        336MB         81.6MB
└─ linux/arm64        e0c1177ee39f       81.5MB         81.5MB
ELF 64-bit LSB executable, ARM aarch64
exec /usr/local/bin/docker-entrypoint.sh: exec format error

The default builder stored both variants under one tag, which Engine 29's containerd 234,762 image store allows and the older overlay2 store did not. The arm64 variant is kept but not unpacked, its node is a genuine AArch64 executable, and it cannot run here, so test it on ARM hardware or under QEMU 34,579 before shipping. docker run picks the host's variant automatically. Hadolint 12,433 accepts --platform=$BUILDPLATFORM but flags a hard-coded platform (rule DL3029).