Repository navigation
Alpine image: linux/arm64 variant ships an x86-64 userland because Dockerfile.alpine pins an amd64-specific base digest #2651
Description
Bug Description
The linux/arm64 variant of the Alpine container image ships an x86-64 userland. The proxy binary itself is correctly cross-compiled for arm64, but busybox, apk, and everything else is x86-64. On arm64 nodes, /bin/sh and all other tools fail with exec format error, and the proxy's --fuse mode is broken because fusermount is an x86-64 binary.
Root cause: the final stage of Dockerfile.alpine pins alpine:3 to an amd64-specific image manifest digest instead of the multi-arch index digest. Digest pinning bypasses buildx platform selection, so the --platform linux/arm64 build silently uses the amd64 rootfs. The pin is unchanged at v2.24.1, so current releases are affected.
The removed bookworm variant (#2630) had the identical defect (see step 3 below), which suggests the digest-update automation systematically resolves platform manifest digests instead of index digests. Suggested fix: pin the index digest for alpine:3 (the tag already publishes linux/arm64 in its manifest list), and fix the automation so the pin does not regress on the next update.
Example code (or command)
# Dockerfile.alpine (unchanged as of v2.24.1) — final stage pins an
# amd64-only manifest digest:
FROM alpine:3@sha256:79ff19e9084a00eece421b2523fb93e22d730e2c0e525905de047e848e56d95f# Runtime symptom on an arm64 node:
$ kubectl exec -it <pod> -c cloud-sql-proxy -- /bin/sh
exec /bin/sh: exec format errorStacktrace
Steps to reproduce?
No arm64 hardware is required; everything below inspects the published images with crane.
- Compare the base rootfs layer of the amd64 and arm64 manifests. They are identical, which is impossible for a correct multi-arch build:
IMG=gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.23-alpine
crane manifest $IMG | jq -r '.manifests[] | select(.platform.os == "linux") | "\(.platform.architecture) \(.digest)"'
# then, for each digest:
crane manifest gcr.io/cloud-sql-connectors/cloud-sql-proxy@<digest> | jq -r '.layers[0].digest'
# Observed:
# amd64 layers[0] = sha256:55afa1ecc21d2bb5e5045f32dafee56272ffd89860bac26f6c32123439af26a4
# arm64 layers[0] = sha256:55afa1ecc21d2bb5e5045f32dafee56272ffd89860bac26f6c32123439af26a4
# (the alpine 3.24.1 x86_64 minirootfs layer)- Confirm that busybox in the arm64 image is an x86-64 ELF:
$ crane export --platform linux/arm64 $IMG - | tar -xO bin/busybox | head -c 20 | xxd
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............
00000010: 0300 3e00 ..>.
# e_machine = 0x3e (EM_X86_64); aarch64 would be 0xb7- (Optional) Confirm the same pattern in the removed bookworm variant:
# 2.23-bookworm shares its base layer across platforms:
# amd64 (sha256:06b15bd1b81bb27956d45da63d574010258ca14f605dbc79e446d6b742873461)
# layers[0] = sha256:20face757db20cd2eddf8149ec7d6b4f1630481ae00d25ad6396bcc5bef5b082
# arm64 (sha256:d80cd7c7689e6e56d76b8f4248513910cc09747eb66d8a91b3e5aef343bbe16a)
# layers[0] = sha256:20face757db20cd2eddf8149ec7d6b4f1630481ae00d25ad6396bcc5bef5b082- (Optional) On any arm64 host, run a shell in the image to observe
the runtime failure:
docker run --rm -it --entrypoint /bin/sh gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.23-alpine
# exec /bin/sh: exec format errorEnvironment
- Image:
gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.23-alpine(linux/arm64variant);Dockerfile.alpinecarries the same pin atv2.24.1, so current releases are affected as well - Host: any linux/arm64 node (e.g. GKE arm64 node pools); the defect is also verifiable host-independently with
craneas above - Tools used for verification:
crane,jq,xxd
Additional Details
No response
Activity
yuhuayang-google commentedon Sep 29, 2026
This was fixed in PR #2681 (commit 85d63dd), which updated
Dockerfile.alpineto pin the multi-arch OCI image index digestalpine:3@sha256:294b683cb724975bec92580e1e685676bd4b50bda910ddb8c51d4cabeaec77e6, which correctly includeslinux/arm64(digestsha256:260479a1cfaf304c4c20da7f8405d3ce313513dcd534bb743257bdd2fe0f3e2d).