Docker Python exec format error: wrong architecture or missing shebang (tested)
exec /usr/local/bin/python: exec format error means the container tried to start a file this machine can't execute. Below it is reproduced on an amd64 host with an arm64 image (at run time and in a RUN step) and with an entrypoint script that lacks a #! line, with the fix for each run.
1. Reproduce: wrong CPU architecture, and a script without #!
The files: a is a plain Python image, b starts through a shell script (once without a #! line, once with one), c has a RUN step:
# ---- a/Dockerfile
FROM python:3-alpine
CMD ["python", "-c", "import platform; print(platform.machine())"]
# ---- b/Dockerfile
FROM python:3-alpine
COPY start.sh start-fixed.sh /
ENTRYPOINT ["/start.sh"]
# ---- b/start.sh
echo "starting app"
exec python -c "print(42)"
# ---- b/start-fixed.sh
#!/bin/sh
echo "starting app"
exec python -c "print(42)"
# ---- c/Dockerfile
FROM python:3-alpine
RUN pip install -q six
run.sh, on an x86_64 (amd64) Linux host with no QEMU emulation registered:
#!/bin/sh
echo "host: $(uname -m)"
echo "== a: image built for arm64, run on this amd64 host"
docker build -q --platform linux/arm64 -t forever-ef410:arm a >/dev/null
docker image inspect --format '{{.Os}}/{{.Architecture}}' forever-ef410:arm
docker run --rm --name forever-ef410run forever-ef410:arm 2>&1
echo "exit code: $?"
echo "== a: same Dockerfile built for amd64"
docker build -q --platform linux/amd64 -t forever-ef410:amd a >/dev/null
docker run --rm --name forever-ef410run forever-ef410:amd 2>&1
echo "== b: ENTRYPOINT script without a #! line"
docker build -q -t forever-ef410:sh b >/dev/null
docker run --rm --name forever-ef410run forever-ef410:sh 2>&1
echo "exit code: $?"
echo "== b: script with #!/bin/sh"
docker run --rm --name forever-ef410run --entrypoint /start-fixed.sh forever-ef410:sh 2>&1
Output (Docker 29.8.1, python:3-alpine):
host: x86_64
== a: image built for arm64, run on this amd64 host
linux/arm64
WARNING: The requested image's platform (linux/arm64) does not match the detected host platform (linux/amd64/v3) and no specific platform was requested
exec /usr/local/bin/python: exec format error
exit code: 255
== a: same Dockerfile built for amd64
x86_64
== b: ENTRYPOINT script without a #! line
exec /start.sh: exec format error
exit code: 255
== b: script with #!/bin/sh
starting app
42
The same thing during a build, when a RUN step has to execute an arm64 binary:
#!/bin/sh
# a RUN step in a cross-platform build without emulation
docker build --platform linux/arm64 --progress=plain -t forever-ef410:c c > build.log 2>&1
echo "build exit code: $?"
grep -E "^#5 .*exec format|^ERROR" build.log
build exit code: 1
#5 0.320 exec /bin/sh: exec format error
ERROR: failed to build: failed to solve: process "/bin/sh -c pip install -q six" did not complete successfully: exit code: 255
2. What the error means
exec ...: exec format error is the Linux kernel refusing to start a file it can't run. In Python containers it is almost always one of two things:
- The image is for another CPU. An image built on an Apple Silicon Mac or a Raspberry Pi is
linux/arm64; on an amd64 server the very first binary (/usr/local/bin/pythonabove, or/bin/shin aRUNstep) fails, exit code 255. Docker prints a "requested image's platform ... does not match the detected host platform" warning first. Check withdocker image inspect --format '{{.Os}}/{{.Architecture}}' IMAGE. - The entrypoint script has no
#!line. In the exec formENTRYPOINT ["/start.sh"]there is no shell, so the kernel needs a shebang to know what runs the file. Adding#!/bin/sh(thestart-fixed.shrun printedstarting appand42) fixes it, as doesENTRYPOINT ["sh", "/start.sh"]. The shebang must be the very first bytes of the file.
3. Fixes for the architecture mismatch
- Build for the machine that will run it:
docker build --platform linux/amd64 ...(thearebuild printedx86_64). In Compose, setplatform: linux/amd64on the service. - Publish a multi-architecture image so each host pulls its own:
docker buildx build --platform linux/amd64,linux/arm64 --push -t NAME .(needs QEMU or native builders for the other arch). - Check for
FROM --platform=...pinned in the Dockerfile; it overrides what you pass on the command line for that stage. - Pure-Python code is portable, but wheels with compiled code are per-architecture, so build the image on (or for) the target platform rather than copying a
site-packagesfolder between machines.
Related: Docker Python ModuleNotFoundError, Docker pip externally-managed-environment, docker build failed.
Frequently asked questions
What causes exec format error in a Docker Python container?
Usually an image built for another CPU architecture (arm64 on amd64 or the reverse), or an entrypoint script without a #! shebang line.
How do I fix exec format error from an image built on a Mac M1/M2?
Rebuild for the server's platform with docker build --platform linux/amd64, or publish a multi-arch image with docker buildx build --platform linux/amd64,linux/arm64.
How do I check which architecture a Docker image is for?
docker image inspect --format '{{.Os}}/{{.Architecture}}' IMAGE
Written with AI assistance. Measured on 2026-10-23 with Docker 29.8.1 and python:3-alpine on an x86_64 Linux host. The scripts ran verbatim and the output was pasted unedited. PlainTables is our extension; Docker and Python are free.