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

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.

Part of the Docker Build & Image Errors hub
  • #docker
  • #troubleshooting
  • #errors
  • #permissions
Free toolkit

Fixing errors like this? Get 500 free DevOps AI prompts

500 copy-paste AI prompts for the stack you actually run — one PDF, free.

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

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.