KhueApps
Home/DevOps/Fix Docker exec format error: architecture mismatch and line endings

Fix Docker exec format error: architecture mismatch and line endings

Last updated: October 07, 2025

Overview

The Docker "exec format error" typically means the kernel can’t execute a file inside the container. Two common causes:

  • Architecture mismatch (e.g., running an amd64 binary on an arm64 host without emulation)
  • Script issues: Windows CRLF line endings, missing/incorrect shebang, or non-executable permissions

This guide shows how to diagnose and fix both quickly.

Symptoms

  • Error messages you may see:
    • exec format error
    • bad interpreter: /bin/sh^M: No such file or directory
    • no such file or directory (when the file exists but the interpreter doesn’t)
SymptomLikely cause
Immediate failure when container starts (even /bin/sh)Image arch ≠ host arch (no emulation)
"^M" in error messageCRLF line endings
"bad interpreter" or "no such file or directory"Wrong shebang or missing shell/interpreter

Quickstart: Fix in minutes

  1. Check host and image architecture:
    • Host: uname -m
    • Image: docker buildx imagetools inspect IMAGE or docker image inspect --format '{{.Architecture}}/{{.Os}}' IMAGE
  2. If mismatched, rebuild or pull the correct platform image:
    • docker build --platform linux/amd64 -t myapp .
    • Or multi-arch: docker buildx build --platform linux/amd64,linux/arm64 -t myuser/myapp:latest --push .
  3. Normalize line endings on scripts before COPY:
    • dos2unix script.sh or git config/text attributes (see below)
  4. Ensure a valid shebang and executable bit:
    • First line: #!/bin/sh (or #!/usr/bin/env bash if bash is installed)
    • chmod +x script.sh
  5. Use JSON-form ENTRYPOINT/CMD in Dockerfile to avoid shell surprises:
    • ENTRYPOINT ["/app/entrypoint.sh"]
  6. If you must run cross-arch locally, enable emulation and expect slower performance:
    • docker run --privileged --rm tonistiigi/binfmt --install all
  7. Verify inside the container:
    • file /app/entrypoint.sh
    • ls -l /app/entrypoint.sh
  8. Rebuild cleanly:
    • docker build --no-cache -t myapp . && docker run --rm myapp

Minimal working example

This example shows a safe script entrypoint and a Dockerfile that avoids line-ending and shebang issues.

entrypoint.sh:

#!/bin/sh
set -eu

printf "Hello from %s on %s\n" "entrypoint" "$(uname -m)"
exec "$@"

Dockerfile:

FROM alpine:3.20
# Avoid CRLF issues by ensuring scripts are LF and executable
WORKDIR /app
COPY entrypoint.sh ./
RUN sed -i 's/\r$//' /app/entrypoint.sh \
    && chmod +x /app/entrypoint.sh

# Demonstrate JSON-form entrypoint
ENTRYPOINT ["/app/entrypoint.sh"]
CMD ["sh", "-c", "echo default cmd"]

Build and run:

# Build for your host arch (auto-detected) or specify explicitly
# Example forcing amd64:
docker build --platform linux/amd64 -t myapp .
docker run --rm myapp

If you accidentally copy a CRLF script without conversion, you might see:

  • bad interpreter: /bin/sh^M: No such file or directory The sed line in the Dockerfile strips CRLF as a safeguard, but prefer fixing line endings in your repo (see below).

Diagnose: Architecture mismatch

  1. Identify host and image arch:
uname -m                               # host arch (e.g., x86_64, aarch64)
docker buildx imagetools inspect IMAGE # shows available platforms
  1. Inspect a local image:
docker image inspect --format '{{.Os}}/{{.Architecture}}' myapp
  1. Run-time checks:
docker run --rm --entrypoint uname IMAGE -m  # prints container arch
  1. Fixes:
  • Build for the correct platform:
docker build --platform linux/arm64 -t myapp:arm64 .
  • Produce multi-arch images with buildx:
docker buildx create --use
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t myuser/myapp:latest \
  --push .
  • Pull the right variant if using official images with manifests:
docker run --platform linux/amd64 ...
  • If cross-running locally, install binfmt emulators (expect overhead):
docker run --privileged --rm tonistiigi/binfmt --install all

Diagnose: Line endings, shebang, permissions

  1. Detect CRLF on host:
file entrypoint.sh              # should say "ASCII text" (no CRLF)
grep -n $'\r' entrypoint.sh || echo "No CRLF"
  1. Convert to LF on host:
dos2unix entrypoint.sh  # or: sed -i 's/\r$//' entrypoint.sh
  1. Enforce LF in Git:
  • One-time setting:
git config core.autocrlf false
  • .gitattributes (commit to repo):
*.sh text eol=lf
Dockerfile text eol=lf
  1. Shebang rules:
  • Use an interpreter that exists in the image:
    • Alpine: /bin/sh (BusyBox ash)
    • Debian/Ubuntu: /bin/sh is dash; /bin/bash requires bash package
  • Portable option:
#!/usr/bin/env bash

Ensure bash is installed if you use it:

RUN apk add --no-cache bash   # Alpine
# or
RUN apt-get update && apt-get install -y --no-install-recommends bash && rm -rf /var/lib/apt/lists/*
  1. Executable bit and JSON entrypoint:
chmod +x entrypoint.sh
ENTRYPOINT ["/app/entrypoint.sh"]
CMD ["your", "args"]

Common pitfalls

  • Building on Windows and copying scripts with CRLF into the image
  • Using /bin/bash in Alpine without installing bash
  • Missing shebang on a script used as ENTRYPOINT or CMD
  • Relying on shell-form ENTRYPOINT which invokes /bin/sh implicitly
  • Hidden BOM at start of file; remove with sed -i '1s/^\xEF\xBB\xBF//' file
  • Running amd64 images on arm64 hosts without binfmt emulation

Performance notes

  • Prefer native-arch images in production. Emulation (qemu-binfmt) can be 2–5× slower.
  • Build multi-arch images once, then pull the matching variant by default.
  • Use buildx with cache to avoid repeated cross-compilation costs:
docker buildx build --platform linux/amd64,linux/arm64 \
  --cache-to type=inline --cache-from type=registry,ref=myuser/myapp:cache \
  -t myuser/myapp:latest --push .
  • Avoid converting line endings inside Dockerfiles on every build; fix them in the repo to keep layers cacheable.

FAQ

Q: Why do I get "no such file or directory" when the script exists? A: The interpreter in the shebang is missing or has CRLF (e.g., /bin/sh^M). Ensure LF endings and a valid interpreter path.

Q: Can I run amd64 images on an arm64 host? A: Yes, with binfmt emulation or Docker Desktop’s built-in qemu. Expect slower performance; prefer native builds for production.

Q: How do I force LF endings in Git on Windows? A: Add .gitattributes with "*.sh text eol=lf" and set git config core.autocrlf false. Re-clone or re-normalize files.

Q: JSON vs shell-form ENTRYPOINT? A: JSON-form avoids invoking /bin/sh and reduces surprises with shebangs and quoting, making startup more predictable.

Series: Docker

DevOps