Files
Anthias/docker/Dockerfile.server.j2
Viktor Petersson 07a8f656e7 fix(ci): pin bun-builder stage to BUILDPLATFORM for 32-bit ARM builds (#2756)
Follow-up to #2755. With the uv image manifest fix in place, master's
buildx matrix surfaced a second 32-bit ARM blocker:

    ERROR: failed to resolve source metadata for
    docker.io/oven/bun:1.3.13-slim: no match for platform in manifest:
    not found

oven/bun publishes only linux/amd64 and linux/arm64 manifests, so a
target-platform build (linux/arm/v7 for pi3, linux/arm/v8 32-bit for
pi4, linux/arm/v6 for pi1/pi2) can't pull the image at all.

The bun-builder stage in Dockerfile.server.j2 only exists to compile
JS/CSS into /app/static/dist/. Its output is platform-independent —
the next stage COPYs the dist tree into the target image. So pin the
stage to $BUILDPLATFORM and let it always run natively on the build
host, regardless of the target. This also avoids a slow
QEMU-emulated `bun run build` on the arm64 builder.

Out of scope: the development branch's `COPY --from=oven/bun:1.3.13-slim
/usr/local/bin/bun` is genuinely platform-dependent (it copies the bun
binary into the runtime image) and not exercised by the production CI
matrix.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 21:49:56 +01:00

63 lines
2.0 KiB
Django/Jinja

{% if environment == 'production' %}
{# bun ships no 32-bit binaries at all — its release artifacts cover
only {linux,darwin,windows}-{x64,aarch64}, so a target-platform
build (linux/arm/v6/v7/v8 for pi1/2/3 and pi4-32) can't pull this
image when bun-builder inherits the target platform. Pin the stage
to $BUILDPLATFORM so it always runs on the build host instead: bun
is only used here to compile JS/CSS into the platform-independent
/app/static/dist/ that the next stage COPYs in, so the host
architecture doesn't matter. This also avoids a slow QEMU-emulated
`bun run build` on arm64 hosts.
Implication: building production images for 32-bit ARM requires an
amd64 or arm64 builder, which is what CI uses. The constraint is
bun itself, not Docker — there's no 32-bit bun binary to fall back
to even outside of Docker, so building this image on a pi3 was
never going to work. If device-local builds ever become a hard
requirement we'd need to either drop bun (e.g. back to Node, which
still ships armv7 binaries) or check `static/dist/` into the
image / a cache and skip this stage entirely. #}
FROM --platform=$BUILDPLATFORM oven/bun:1.3.13-slim AS bun-builder
RUN mkdir -p /app
WORKDIR /app
COPY package.json \
bun.lock \
tsconfig.json \
/app/
RUN bun install --frozen-lockfile
COPY ./static/sass/*.scss /app/static/sass/
COPY ./static/src/ /app/static/src/
RUN bun run build
{% endif %}
{% include 'uv-builder.j2' %}
{% include 'Dockerfile.base.j2' %}
COPY --from=uv-builder /venv /venv
ENV PATH="/venv/bin:$PATH"
ENV VIRTUAL_ENV="/venv"
RUN mkdir -p /usr/src/app
COPY . /usr/src/app/
WORKDIR /usr/src/app
{% if environment == 'production' %}
COPY --from=bun-builder \
/app/static/dist/ \
/usr/src/app/static/dist/
{% else %}
COPY --from=oven/bun:1.3.13-slim /usr/local/bin/bun /usr/local/bin/bun
RUN ln -sf bun /usr/local/bin/bunx
{% endif %}
ENV GIT_HASH={{ git_hash }}
ENV GIT_SHORT_HASH={{ git_short_hash }}
ENV GIT_BRANCH={{ git_branch }}
ENV DEVICE_TYPE={{ board }}
CMD ["bash", "bin/start_server.sh"]