Summary
ghcr.io/turbootzz/vaultwarden-api:latest ships the amd64 binary in every architecture's manifest entry. On arm64 / arm/v7 the container fails immediately:
exec /app/vaultwarden-api: exec format error
Evidence
$ docker create --platform linux/amd64 ghcr.io/turbootzz/vaultwarden-api:latest
$ file vaultwarden-api
ELF 64-bit LSB executable, x86-64 ... Go BuildID=0sXONm1iirQfpSCGmJK0/G_t_NpmrNQA9-...
$ docker create --platform linux/arm64 ghcr.io/turbootzz/vaultwarden-api:latest
$ file vaultwarden-api
ELF 64-bit LSB executable, x86-64 ... Go BuildID=0sXONm1iirQfpSCGmJK0/G_t_NpmrNQA9-...
amd64, arm64 and arm/v7 all carry the identical Go BuildID - the same GOARCH=amd64 compile, relabelled per platform.
Cause
Dockerfile:
ARG TARGETOS=linux
ARG TARGETARCH=amd64
RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build ...
TARGETOS / TARGETARCH are BuildKit predefined build args. Redeclared with an explicit default, the default wins over the platform-derived value BuildKit would inject - so GOARCH is pinned to amd64 for every --platform.
Fix
Drop the defaults so BuildKit populates them per target platform:
ARG TARGETOS
ARG TARGETARCH
Downstream workaround
--build-arg TARGETARCH=<arch> overrides the Dockerfile default:
docker buildx build --platform linux/arm64 --build-arg TARGETARCH=arm64 ...
Summary
ghcr.io/turbootzz/vaultwarden-api:latestships the amd64 binary in every architecture's manifest entry. On arm64 / arm/v7 the container fails immediately:Evidence
amd64, arm64 and arm/v7 all carry the identical Go BuildID - the same
GOARCH=amd64compile, relabelled per platform.Cause
Dockerfile:TARGETOS/TARGETARCHare BuildKit predefined build args. Redeclared with an explicit default, the default wins over the platform-derived value BuildKit would inject - soGOARCHis pinned toamd64for every--platform.Fix
Drop the defaults so BuildKit populates them per target platform:
Downstream workaround
--build-arg TARGETARCH=<arch>overrides the Dockerfile default: