Skip to content
DevOps AI ToolKit
Newsletter
All guides
Docker with AI By James Joyner IV · · 9 min read

Docker Error Guide: 'exec /entrypoint.sh: no such file or directory' Entrypoint Startup Failures

Fix Docker 'exec /entrypoint.sh: no such file or directory': repair CRLF line endings, missing shells, wrong arch, and unset executable bits on entrypoints.

  • #docker
  • #troubleshooting
  • #errors
  • #runtime

Exact Error Message

exec ...: no such file or directory fires the instant a container starts and the runtime tries to execute its entrypoint or command:

docker run app:latest

exec /entrypoint.sh: no such file or directory

It also appears for binaries and interpreters, often confusingly when the file clearly exists:

exec /usr/local/bin/app: no such file or directory
exec /app/server: exec format error

The container exits immediately with a non-zero code. The image built fine; the failure is purely at process exec.

What the Error Means

When a container starts, the OCI runtime calls execve() on the configured entrypoint/command. The kernel’s execve returns ENOENT (“no such file or directory”) in three situations that all surface as the same message:

  1. The file itself is missing at the path Docker tried — a real “not found.”
  2. The interpreter named in the shebang is missing. For a script starting with #!/bin/bash, if /bin/bash doesn’t exist in the image (common on alpine, which has /bin/sh but not bash), the kernel reports ENOENT for the interpreter, not the script — but the error names the script.
  3. The shebang line is corrupted by CRLF line endings. A script edited on Windows ends its shebang with \r, so the kernel looks for /bin/bash\r, which doesn’t exist — again ENOENT.

A close cousin, exec format error, means the file exists and is reachable but is built for the wrong architecture (an amd64 binary on arm64) or isn’t a valid executable. The no such file or directory family is overwhelmingly shebang/CRLF/missing-interpreter, not a truly absent file.

Common Causes

  • CRLF line endings in the script, so the shebang becomes #!/bin/sh\r.
  • Missing interpreter#!/bin/bash in an image that only ships /bin/sh (alpine/distroless/scratch).
  • The entrypoint genuinely isn’t in the image (wrong COPY path, copied to the wrong stage, or .dockerignore excluded it).
  • Not executable — the file lacks the +x bit (surfaces as permission denied or, combined with shebang issues, as not found).
  • Wrong architecture — an image or binary built for a different CPU (exec format error).
  • Dynamically linked binary in scratch/distroless missing its loader (/lib/ld-musl or glibc), which the kernel reports as not found.

How to Reproduce the Error

Author a script with Windows line endings and run it in a container:

printf '#!/bin/sh\r\necho hello\r\n' > entrypoint.sh
chmod +x entrypoint.sh
printf 'FROM alpine:3.20\nCOPY entrypoint.sh /entrypoint.sh\nENTRYPOINT ["/entrypoint.sh"]\n' > Dockerfile
docker build -t crlf-demo . && docker run --rm crlf-demo
exec /entrypoint.sh: no such file or directory

Diagnostic Commands

First confirm whether the file is even in the image and is executable. Override the entrypoint to get a shell:

docker run --rm -it --entrypoint sh app:latest -c 'ls -l /entrypoint.sh; head -1 /entrypoint.sh | cat -A'

cat -A reveals a trailing ^M$ (CRLF) on the shebang line — the smoking gun. Check the interpreter exists:

docker run --rm -it --entrypoint sh app:latest -c 'ls -l /bin/bash /bin/sh 2>&1'

Confirm the image/binary architecture matches the host:

docker image inspect app:latest --format 'image: {{.Architecture}}'
docker version --format 'engine: {{.Server.Arch}}'

Read the daemon log for the runtime’s exec failure:

journalctl -u docker --since "10 min ago" | grep -i 'exec\|no such file\|format error'

Step-by-Step Resolution

Cause: CRLF line endings. Convert the script to Unix endings and rebuild. In the Dockerfile you can also normalize during build, or fix the source with dos2unix/sed before COPY. The reliable fix is at the source so it can’t regress:

COPY entrypoint.sh /entrypoint.sh
RUN sed -i 's/\r$//' /entrypoint.sh && chmod +x /entrypoint.sh

Cause: missing interpreter. Either change the shebang to one the image has (#!/bin/sh on alpine) or install the interpreter (RUN apk add bash). For distroless/scratch, ship a static binary or include the shell explicitly.

Cause: file not in image. Verify the COPY source path, the build stage, and .dockerignore. The ls -l from the diagnostics confirms presence; fix the COPY so the file lands at the expected path.

Cause: not executable. Add the bit in the Dockerfile so it’s baked into the layer:

RUN chmod +x /entrypoint.sh

Cause: wrong architecture (exec format error). Pull/build for the host’s platform, or run under emulation. Build with --platform matching the target and verify with docker image inspect.

A worked example. A developer’s image ran fine on their Mac but every teammate on Linux hit exec /entrypoint.sh: no such file or directory. The script had been committed with CRLF endings from a Windows editor; the Mac’s tooling tolerated it but the Linux kernel looked for /bin/sh\r. docker run --entrypoint sh ... -c 'head -1 /entrypoint.sh | cat -A' showed #!/bin/sh^M$. Adding RUN sed -i 's/\r$//' /entrypoint.sh to the Dockerfile and a .gitattributes rule (*.sh text eol=lf) fixed it permanently across the team.

Prevention and Best Practices

  • Enforce LF endings on shell scripts with a .gitattributes rule (*.sh text eol=lf) and a lint check in CI.
  • Match the shebang to what the base image actually ships (/bin/sh on alpine; install bash if you need it).
  • Set the executable bit in the Dockerfile (RUN chmod +x ...) rather than relying on the host file mode.
  • Build for the correct --platform and verify image architecture before deploying.
  • For scratch/distroless, prefer static binaries or include the interpreter and its loader explicitly.

Frequently Asked Questions

The file is clearly there — why “no such file”? The kernel is usually reporting the interpreter in the shebang (or a \r-mangled version of it) as missing, not the script. Inspect the first line with cat -A.

How do I tell CRLF from a missing interpreter? head -1 file | cat -A shows ^M$ for CRLF. If the shebang is clean, check that the named interpreter (/bin/bash) exists in the image.

What’s the difference from exec format error? That means the file is found and runnable but built for the wrong architecture or isn’t a valid binary. no such file is about the path/interpreter, not the binary format.

Does chmod +x on my host fix it? Only if you re-COPY after, and only for the exec bit. CRLF and missing-interpreter problems need a content/shebang fix, not just permissions.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.