Skip to content
DevOps2026-09-083 min read

Executable File Not Found: 4 Reasons Docker Containers Exit Instantly (incl. exec format error)

Symptom: the container dies a second after starting

# At container start
standard_init_linux.go: exec: "./start.sh": stat ./start.sh: no such file or directory

# Or with docker exec
OCI runtime exec failed: exec: "sh": executable file not found in $PATH: unknown

# Or another form
exec ./start.sh: no such file or directory

One-line diagnosis: the file or command you told the container to execute can't be found inside it. The trap: when it says no such file or directory, the file is often right there — what's actually missing is the script's interpreter (the program the shebang points to). This is the most misleading error message Docker has.

Four causes, ranked by frequency

1. Windows CRLF line endings broke the shebang (the sneaky one)

A shell script edited on Windows has \r\n endings, so line one actually reads:

#!/bin/sh\r

Linux looks for a program called sh\r — it doesn't exist, so you get no such file or directory while ls shows the script sitting right there. Verify and fix:

docker run --rm --entrypoint sh myapp -c "head -1 /app/start.sh | od -c | head -2"
# \r  \n in the output is the smoking gun

# Fix: add to the repo's .gitattributes
*.sh text eol=lf

Or switch the editor from CRLF to LF and re-save.

2. ENTRYPOINT exec form with variable interpolation

# ❌ exec form never spawns a shell: $JAVA_OPTS stays literal
ENTRYPOINT ["java", "$JAVA_OPTS", "-jar", "app.jar"]

# ✅ to expand variables use shell form (note: loses signal forwarding)
ENTRYPOINT java ${JAVA_OPTS} -jar app.jar

Exec form ["a","b"] starts no shell$VAR, ~, and globs stay literal; shell form a b goes through /bin/sh -c, so variables expand. Confusing the two forms is a top source of this error. Likewise, ENTRYPOINT ["npm", "start"] failing to find npm usually means npm isn't on PATH in the base image or lives under another user's home.

3. Paths: relative paths and WORKDIR

WORKDIR /app
COPY start.sh .            # file is at /app/start.sh
ENTRYPOINT ["./start.sh"]  # ✅ relative to WORKDIR
ENTRYPOINT ["/start.sh"]   # ❌ nothing at root

Fastest check is to exec in and look around:

docker run --rm --entrypoint sh myapp -c "ls -la /app && which npm"

4. Architecture mismatch: exec format error

exec /app/start.sh: exec format error

An arm64 image built on an M-series Mac running on an x86 server (or vice versa). Not a missing file — the binary format is wrong. Lock the platform at build time:

docker buildx build --platform linux/amd64 -t myapp --push .

Confirm with docker inspect --format '{{.Architecture}}' myapp.

The debugging trio

# 1. What entry did the image actually configure?
docker inspect myapp --format '{{json .Config.Entrypoint}} {{json .Config.Cmd}}'

# 2. Bypass the entrypoint and inspect the scene
docker run --rm --entrypoint sh myapp
# inside: ls the files, head -1 xxx.sh | od -c for CRLF, which xxx for PATH

# 3. Run pieces of the Dockerfile step by step — the failing step reveals itself
docker run --rm myapp ls /app

Checklist

  1. Is the file actually there? --entrypoint sh, then ls
  2. There but "not found"? od -c the shebang for CRLF (nine out of ten Windows-edited scripts)
  3. Exec-form ENTRYPOINT with $VAR? Switch to shell form or an entrypoint script
  4. Relative paths resolve against WORKDIR, not the directory you imagined
  5. exec format error → architecture mismatch, rebuild with buildx --platform

Provided by ToolVault. Related tools: Dockerfile Generator, Linux Cheatsheet. Related reading: Docker daemon unreachable, Container name conflicts. See the homepage for more developer tools.


Advertisement