Docker — exec format error on container start
Diagnose exec format errors caused by an arm64/amd64 image or binary mismatch, verify the platform digest, and build a multi-architecture image.
Symptoms
- standard_init_linux.go: exec user process caused: exec format error
- The container exits immediately, often with status 1 or 255
- The image works on a developer's Apple Silicon laptop but fails on an amd64 server
- A compiled binary runs locally but not inside the container
Possible causes
- The image was built for a different CPU architecture than the host
- A binary was compiled on the host and copied into a different base image
- The base image tag resolves to a single-architecture manifest
- CI built without a platform and pushed an arm64 image to an amd64 cluster
- A cross-build produced the wrong GOARCH or target triple
Diagnosis steps
Compare the host and image architectures
uname -m && docker image inspect IMAGE --format '{{.Os}}/{{.Architecture}}'Interpretation
An arm64 image on an amd64 host, or the reverse, is the usual cause. The inspect output shows the image's declared platform.
Inspect the registry manifest
docker buildx imagetools inspect IMAGE:TAGInterpretation
A single-platform manifest confirms the tag is not multi-arch. A multi-arch index lists the available platforms.
Check the binary format inside the image
docker run --rm --entrypoint sh IMAGE -c 'uname -m'Interpretation
If the container cannot start at all, copy the binary out or use a debug base image to run file(1) and read the ELF header.
Root cause
The Linux kernel cannot execute the entry point because its binary format or CPU architecture does not match the host. The image or a binary inside it was built for a different platform.
Fix
Build for the deployment platform with docker buildx --platform, publish a multi-arch manifest, and make sure compiled artifacts use the target architecture. Pin the platform in CI and verify the pushed digest.
Risk note
Emulation such as QEMU can run foreign-architecture images for debugging, but it is slow and should not be the production solution. A silently emulated image hides the build mismatch.
Verify the fix
Run the image on a host with the deployment architecture and confirm the entry point starts. Inspect the pushed digest with imagetools and deploy by digest, not by a mutable tag.
The kernel is telling you the truth
exec format error is not a missing dependency or a permissions problem. The kernel read the entry point and could not execute it as a native binary. On ARM hosts, an amd64-only image fails this way; on amd64 hosts, an arm64 image does. The same error appears when a host-compiled binary copied into a Linux image uses the wrong OS or architecture.
uname -m
docker image inspect myapp:latest --format '{{.Os}}/{{.Architecture}}'
If the two strings disagree, stop debugging the application. Rebuild for the target platform.
Build a multi-architecture image
A multi-arch image is an index that points to one image per platform. The registry serves the matching image to each host:
docker buildx create --use --name multiarch
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t registry.example.com/myapp:1.4.0 \
--push .
The build must actually support both platforms. If the Dockerfile downloads a prebuilt binary, select the binary by TARGETARCH; if it compiles, use a cross-compilation stage. A multi-arch manifest with identical single-arch layers is worse than no manifest because it looks correct until runtime.
Verify the digest you deploy
Tags can be moved. After the push, inspect the manifest and deploy by digest so the cluster receives the image you tested. In Kubernetes, use the digest in the pod spec and confirm the node architecture matches the scheduler constraint. For local debugging, docker run --platform linux/amd64 can force a specific image, but it requires emulation and is not a production fix.
Check the whole chain
A correct base image does not guarantee a correct binary. A Go build with the wrong GOARCH, a Node native addon compiled on the host, or a copied CLI tool can each produce the error. Inspect the entry point and any native dependencies, not only the base image tag.