Fix: Docker exec format error
Quick Answer
How to fix Docker exec format error caused by architecture mismatch (ARM vs x86), missing shebang line, wrong entrypoint, and multi-platform build issues.
The Error
You run a Docker container and get:
exec /usr/local/bin/docker-entrypoint.sh: exec format errorOr variations:
standard_init_linux.go:228: exec user process caused: exec format errorexec /app/start.sh: exec format errorexec /usr/bin/python3: exec format errorThe container starts but immediately exits with this error. Docker cannot execute the entrypoint or command because the binary format is incompatible with the container’s architecture or the script is malformed.
Why This Happens
Two main causes:
Architecture mismatch. The image was built for a different CPU architecture. An image built for
linux/amd64(Intel/AMD) cannot run onlinux/arm64(Apple Silicon, AWS Graviton) and vice versa.Missing or wrong shebang line. A shell script used as the entrypoint does not have a proper
#!/bin/bashor#!/bin/shline at the top, so the kernel does not know how to execute it.
Less common causes:
- Windows line endings in scripts.
\r\nline endings in shell scripts cause the shebang interpreter to not be found. - Binary compiled for wrong OS. A macOS or Windows binary inside a Linux container.
- Corrupted binary. The executable file is damaged.
Fix 1: Fix Architecture Mismatch
Check the image’s architecture:
docker inspect --format='{{.Architecture}}' my-imageCheck your host’s architecture:
uname -m
# x86_64 = amd64
# aarch64 = arm64Common mismatch: Building on an Apple Silicon Mac (arm64) and deploying to an x86_64 server, or vice versa.
Fix: Build for the target architecture:
# Build for amd64 (Intel/AMD servers)
docker build --platform linux/amd64 -t my-app .
# Build for arm64 (Apple Silicon, AWS Graviton)
docker build --platform linux/arm64 -t my-app .Fix: Build multi-platform images:
# Create a builder that supports multiple platforms
docker buildx create --use
# Build for both architectures
docker buildx build --platform linux/amd64,linux/arm64 -t my-app --push .This creates a manifest that includes images for both architectures. Docker automatically pulls the correct one.
Pro Tip: Always use
--platform linux/amd64in CI/CD pipelines that deploy to x86_64 servers, even if the CI runner is ARM-based. This prevents architecture mismatch surprises in production.
Fix 2: Add the Shebang Line
Shell scripts must start with a shebang line that tells the kernel which interpreter to use:
Broken — missing shebang:
# start.sh
echo "Starting app..."
exec python3 app.pyFixed:
#!/bin/bash
echo "Starting app..."
exec python3 app.pyOr for maximum portability:
#!/bin/sh
echo "Starting app..."
exec python3 app.pyIn Alpine-based images, use /bin/sh:
Alpine uses ash (BusyBox), not bash. If your script starts with #!/bin/bash but the image does not have bash:
exec /app/start.sh: exec format errorFix: Use #!/bin/sh or install bash:
# Option 1: Use sh
# In start.sh: #!/bin/sh
# Option 2: Install bash
RUN apk add --no-cache bashFix 3: Fix Windows Line Endings (CRLF)
If you develop on Windows, scripts might have \r\n (CRLF) line endings. The kernel reads the shebang as #!/bin/bash\r and tries to find an interpreter called bash\r — which does not exist.
Fix: Convert line endings in the Dockerfile:
COPY start.sh /app/start.sh
RUN sed -i 's/\r$//' /app/start.sh && chmod +x /app/start.shFix: Convert before building:
# Linux/macOS
sed -i 's/\r$//' start.sh
# Or using dos2unix
dos2unix start.shFix: Use .gitattributes to prevent CRLF in the repo:
*.sh text eol=lf
Dockerfile text eol=lfCommon Mistake: Building Docker images on Windows without configuring line endings. Git on Windows converts
\nto\r\nby default (core.autocrlf=true). This silently corrupts shell scripts. Always seteol=lfin.gitattributesfor scripts and Dockerfiles.
Fix 4: Fix the Entrypoint in Dockerfile
A wrong entrypoint format can cause exec format error:
Broken — shell form without shebang:
COPY app.py /app/
ENTRYPOINT python3 /app/app.pyIf Docker uses exec form internally and python3 is not found in the expected location, you get the error.
Fixed — exec form (preferred):
ENTRYPOINT ["python3", "/app/app.py"]Fixed — shell form with explicit shell:
ENTRYPOINT ["/bin/sh", "-c", "python3 /app/app.py"]For custom scripts:
COPY start.sh /app/start.sh
RUN chmod +x /app/start.sh
ENTRYPOINT ["/app/start.sh"]Make sure start.sh has the shebang line and correct line endings.
Fix 5: Fix Docker Compose Platform
Specify the platform in docker-compose.yml:
services:
app:
image: my-app:latest
platform: linux/amd64Or build with the platform:
services:
app:
build:
context: .
dockerfile: Dockerfile
platforms:
- linux/amd64This is especially important on Apple Silicon Macs where Docker defaults to linux/arm64, but many images only support linux/amd64.
Fix 6: Fix Python/Node Binary Issues
If the exec format error points to a language runtime binary:
exec /usr/bin/python3: exec format errorThe base image was built for a different architecture.
Fix: Use the correct base image:
# This automatically picks the right architecture:
FROM python:3.12-slim
# Or explicitly specify:
FROM --platform=linux/amd64 python:3.12-slimFix: Check available architectures for the image:
docker manifest inspect python:3.12-slim | grep architectureFor Docker daemon issues that prevent containers from starting at all, see Fix: Docker daemon is not running.
Fix 7: Fix Compiled Binaries
If you copy a pre-compiled binary into the container, it must match the container’s architecture:
Broken:
# Binary compiled on macOS ARM
COPY ./my-app /app/my-app
ENTRYPOINT ["/app/my-app"]Fixed — compile inside the container:
FROM golang:1.22 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o my-app
FROM alpine:3.19
COPY --from=builder /app/my-app /app/my-app
ENTRYPOINT ["/app/my-app"]For Rust:
FROM rust:1.77 AS builder
WORKDIR /app
COPY . .
RUN cargo build --release --target x86_64-unknown-linux-musl
FROM alpine:3.19
COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/my-app /app/my-app
ENTRYPOINT ["/app/my-app"]Always compile inside the Docker build stage to ensure architecture compatibility.
Fix 8: Debug the Error
Check the file type:
docker run --entrypoint file my-image /app/start.sh
# Should show: Bourne-Again shell script, ASCII text executable
# If it shows: data — the file is corrupted or has wrong formatCheck the binary architecture:
docker run --entrypoint file my-image /usr/bin/python3
# Should show: ELF 64-bit LSB executable, x86-64
# If it shows: ELF 64-bit LSB executable, ARM aarch64 — architecture mismatchCheck for missing dependencies:
docker run --entrypoint ldd my-image /app/my-app
# Shows dynamic library dependencies
# "not found" entries indicate missing librariesIf the error is about image pulling rather than execution, see Fix: Docker image not found. For container permission issues, see Fix: Docker volume permission denied.
Still Not Working?
Check for QEMU emulation. Docker Desktop on Mac and Windows uses QEMU to run images for different architectures. QEMU is slower and can fail with complex binaries. If possible, use native architecture images.
Check for static vs dynamic linking. Dynamically linked binaries need the correct shared libraries. Alpine uses musl instead of glibc. A binary linked against glibc fails on Alpine:
# Use a glibc-based image instead of Alpine:
FROM debian:12-slimOr compile with static linking.
Check for BOM (Byte Order Mark). Some editors add a BOM at the beginning of files. This invisible character breaks the shebang line. Check with:
xxd start.sh | head -1
# Should start with 2321 (#!/) not efbb bf23 (BOM + #!/)Remove the BOM with:
sed -i '1s/^\xEF\xBB\xBF//' start.shCheck Docker Desktop settings. On macOS, Docker Desktop has a “Use Rosetta for x86_64/amd64 emulation on Apple Silicon” option. Enabling this can improve compatibility with amd64 images. For disk space issues preventing image pulls, see Fix: Docker no space left on device.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: Docker container health status unhealthy
How to fix Docker container health check failing with unhealthy status, including HEALTHCHECK syntax, timing issues, missing curl/wget, endpoint problems, and Compose healthcheck configuration.
Fix: Docker build sending large build context / slow Docker build
How to fix Docker build sending large build context caused by missing .dockerignore, node_modules in context, large files, and inefficient Dockerfile layers.
Fix: Docker Build Cache Not Working - No Cache Being Used
How to fix Docker build cache not working when layers rebuild every time despite no changes, including layer ordering, .dockerignore, COPY invalidation, BuildKit cache mounts, and CI/CD cache strategies.
Fix: Docker Compose Service failed to build / ERROR building
How to fix Docker Compose Service failed to build errors caused by wrong Dockerfile paths, YAML syntax issues, build args, platform mismatches, and network failures.