Skip to content
DevOps AI ToolKit
All guides
Docker with AI By James Joyner IV · · 9 min read Last reviewed Jul 2026

Docker Error Guide: 'OCI runtime exec failed: permission denied' — Fix Non-Executable Entrypoints

Quick answer

Fix Docker 'OCI runtime exec failed permission denied': set the executable bit on entrypoints, handle CRLF and missing interpreters, and resolve noexec mounts and security policies.

  • #docker
  • #troubleshooting
  • #errors
  • #permissions
Free toolkit

Stuck on this Docker with AI error? Get the free incident triage checklist

A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.

Overview

Docker (via runc) raises this when it can locate the process you asked to run but the kernel refuses to execute it:

OCI runtime exec failed: exec failed: unable to start container process: exec: "/entrypoint.sh": permission denied: unknown

The same shape appears on docker run (unable to start container process) and on docker exec. The key phrase is permission denied — the file exists, but it is either not executable, has a broken interpreter line, or is being run from a mount that forbids execution.

Symptoms

  • docker run exits immediately with OCI runtime create failed ... permission denied.
  • docker exec -it <id> /some/script.sh returns permission denied even though the file is clearly present.
  • The image built fine but never starts; the entrypoint script is the culprit.
  • A bind-mounted script works on one host and fails on another.

Common Root Causes

  • Missing executable bit — the entrypoint or command file was copied without +x (common when scripts are added on a Windows or CI filesystem).
  • CRLF line endings / bad shebang — a script starting with #!/bin/sh\r makes the kernel look for an interpreter named sh\r, which fails.
  • Missing interpreter — the shebang points to /bin/bash but the (slim/alpine) image only has /bin/sh.
  • noexec mount — the script lives on a bind mount or tmpfs mounted with noexec, so execution is blocked regardless of file bits.
  • Directory, not a file — the entrypoint path resolves to a directory.
  • Security policy — SELinux, AppArmor, or a seccomp profile denies the exec.

Diagnostic Workflow

Verify the file’s permissions and type inside the image without running the failing entrypoint:

docker run --rm --entrypoint sh myapp:1.4.2 -c 'ls -l /entrypoint.sh; file /entrypoint.sh'

A mode like -rw-r--r-- (no x) is the smoking gun. Check the shebang and hunt for a carriage return:

docker run --rm --entrypoint sh myapp:1.4.2 -c 'head -1 /entrypoint.sh | od -c | head -1'

A trailing \r confirms CRLF endings. Confirm the interpreter actually exists:

docker run --rm --entrypoint sh myapp:1.4.2 -c 'ls -l /bin/bash /bin/sh 2>&1'

If the script is bind-mounted, check for a noexec mount on the host:

mount | grep noexec

For security-policy denials, check the daemon and kernel logs:

journalctl -u docker --since '10 min ago' | grep -i 'permission\|apparmor\|seccomp'
dmesg | tail -20 | grep -i 'denied\|apparmor'

Example Root Cause Analysis

A CI pipeline built myapp:1.4.2 successfully, but every deploy crashed with OCI runtime create failed: unable to start container process: exec: "/entrypoint.sh": permission denied.

Inspecting the file inside the image showed no executable bit:

docker run --rm --entrypoint sh myapp:1.4.2 -c 'ls -l /entrypoint.sh'
# -rw-r--r-- 1 root root 412 /entrypoint.sh

The Dockerfile had COPY entrypoint.sh /entrypoint.sh but never made it executable, and the source file (checked out on a Windows CI runner) had lost its mode bit. The fix was to set the bit explicitly at build time and normalize line endings:

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

After rebuilding, ls -l showed -rwxr-xr-x and the container started cleanly.

Prevention Best Practices

  • Always chmod +x entrypoint scripts in the Dockerfile (or commit them with the executable bit and a .gitattributes * text=auto eol=lf rule to prevent CRLF).
  • Match the shebang to what the base image ships — use #!/bin/sh for alpine/slim images that lack bash.
  • Avoid mounting scripts from noexec filesystems; bake them into the image instead.
  • Prefer the exec form (ENTRYPOINT ["/entrypoint.sh"]) and test the image locally before shipping.
  • Lint your build with the Dockerfile validator and follow the runtime conventions in the Docker stack guide.

Quick Command Reference

docker run --rm --entrypoint sh myapp:1.4.2 -c 'ls -l /entrypoint.sh; file /entrypoint.sh'
docker run --rm --entrypoint sh myapp:1.4.2 -c 'head -1 /entrypoint.sh | od -c | head -1'  # CRLF check
mount | grep noexec                                       # noexec bind mount?
dmesg | tail -20 | grep -i 'apparmor\|denied'             # security policy?
# In the Dockerfile:
# RUN sed -i 's/\r$//' /entrypoint.sh && chmod +x /entrypoint.sh

Conclusion

OCI runtime exec failed ... permission denied means the kernel found the file but would not run it. Ninety percent of the time it is a missing executable bit or CRLF line endings on the entrypoint; the rest is a missing interpreter, a noexec mount, or a security policy. Inspect the file with ls -l and check the shebang, then fix the root cause in the Dockerfile with chmod +x and LF normalization rather than working around it at runtime.

Free download · 368-page PDF

Fixed it? Get 500 Docker with AI & DevOps AI prompts — free

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.

Stuck on this? Start guided troubleshooting

Open an interactive diagnostic session with this error already loaded. Work a step-by-step plan, record what each check returns, land on a root cause, and export a clean incident summary — no account needed to start.

Did this fix your issue?

Solved it a different way?

Share the fix that worked for you — reviewed, then published to help the next engineer.

Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

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.