Docker Error Guide: 'OCI runtime exec failed: permission denied' — Fix Non-Executable Entrypoints
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
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 runexits immediately withOCI runtime create failed ... permission denied.docker exec -it <id> /some/script.shreturnspermission deniedeven 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\rmakes the kernel look for an interpreter namedsh\r, which fails. - Missing interpreter — the shebang points to
/bin/bashbut 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 +xentrypoint scripts in the Dockerfile (or commit them with the executable bit and a.gitattributes* text=auto eol=lfrule to prevent CRLF). - Match the shebang to what the base image ships — use
#!/bin/shfor alpine/slim images that lack bash. - Avoid mounting scripts from
noexecfilesystems; 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.
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.