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
- Is the file actually there?
--entrypoint sh, thenls - There but "not found"?
od -cthe shebang for CRLF (nine out of ten Windows-edited scripts) - Exec-form ENTRYPOINT with
$VAR? Switch to shell form or an entrypoint script - Relative paths resolve against WORKDIR, not the directory you imagined
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.
Related Tools
Related Articles
Permission denied (publickey): 6 Reasons Git Push Fails Over SSH (and the Fix for Each)
git clone or push rejected with Permission denied (publickey) fatal: Could not read from remote repository? Covers missing keygen, key not loaded in the agent, public key not added to GitHub/GitLab, multi-account key routing with ~/.ssh/config, deploy key limits, and wrong remote URLs — with ssh -v diagnostics.
error:0308010C digital envelope routines::unsupported — Fixing Node 17+ Breakage in Older Projects
Node 17+ crashes webpack 4 builds with error:0308010C:digital envelope routines::unsupported because OpenSSL 3.0 removed MD4. Three fixes compared: --openssl-legacy-provider quick unblock, upgrading to webpack 5 as the real fix, and pinning Node 16 as a stopgap.
ECONNREFUSED: Connection Refused — 5 Causes Explained (Including Docker)
Node, Java, or curl reporting connect ECONNREFUSED 127.0.0.1:3306? It means nothing is listening on that port. Covers service not running, wrong port, 127.0.0.1-only binding, Docker container networking, and firewall REJECT rules — with ss/lsof diagnostic commands.