Docker Error: OCI runtime create failed: unable to start container process: executable file not found
Convert entrypoint shell scripts from Windows CRLF (\r\n) to Unix LF (\n) line endings using .gitattributes or dos2unix, and ensure chmod +x entrypoint.sh.
Root Cause Analysis
This error occurs when Python or the Docker container runtime (runc) tries to launch a container's entrypoint script, but the Linux kernel cannot execute the file because Windows carriage return line endings (\r\n) corrupted the shebang interpreter line (#!/bin/sh\r), making Linux look for an executable literally named sh\r which does not exist.
The Windows CRLF Shebang Trap
On Windows workstations, text editors (and Git checkouts without .gitattributes) save shell scripts with DOS/Windows line endings (\r\n / CRLF). When a file starting with #!/bin/sh\r\n is copied into a Linux Docker container image via COPY entrypoint.sh .:
- The Linux kernel's ELF binary loader reads the shebang line to find the interpreter.
- It interprets
/bin/sh\ras the full interpreter path (including the invisible carriage return character\r/\x0d). - Since no file named
/bin/sh\rexists in/bin,runcfails withOCI runtime create failed: runc create failed: unable to start container process: exec: ".": executable file not found in $PATH.
Other Common Causes
- Missing Execute Permissions: Creating a shell script on Windows that lacks the Linux execute permission bit (
chmod +x). - JSON Exec Form vs Shell Form Syntax in Dockerfile: Writing
ENTRYPOINT ["./entrypoint.sh"]when the script was copied to/app/entrypoint.shwithout a matchingWORKDIR /app.
Reproduction Code (MCVE)
# Simulates runtime failure when an entrypoint shebang contains carriage return \r\n
shebang = b'#!/bin/sh\r\n'
if b'\r' in shebang:
raise RuntimeError('OCI runtime create failed: unable to start container process: exec: ".": executable file not found')
Solution 1: Enforce Unix LF Line Endings via `.gitattributes`
Add a .gitattributes file to the root of your repository to ensure Git always checks out shell scripts with Unix LF line endings across all operating systems.
gitattributes_content = '''
# Enforce LF line endings for all shell scripts in Docker builds
*.sh text eol=lf
Dockerfile text eol=lf
requirements.txt text eol=lf
'''
print('Configured .gitattributes rules:')
print(gitattributes_content.strip())
Solution 2: Use Explicit Shell Invocation in Dockerfile
Invoke the shell interpreter directly in the Dockerfile ENTRYPOINT or convert the script using dos2unix in the Docker build step.
dockerfile_snippet = '''
# Method A: Direct shell interpreter invocation
ENTRYPOINT ["/bin/sh", "/app/entrypoint.sh"]
# Method B: Clean line endings during Docker image build
RUN apt-get update && apt-get install -y dos2unix \
&& dos2unix /app/entrypoint.sh \
&& chmod +x /app/entrypoint.sh
'''
print('Recommended Dockerfile entrypoint configurations:')
print(dockerfile_snippet.strip())
Note de reproductibilité
La reproductibilité de cette erreur dépend du système d'exploitation de développement (Windows vs macOS/Linux) et de la configuration des fins de ligne (CRLF vs LF) par Git lors du clonage du projet.
Edge Cases & Docker Multi-Stage Permissions
When copying files between stages in multi-stage Docker builds (COPY --from=builder /app /app), permissions can be altered. Always use COPY --chmod=755 --from=builder /app/entrypoint.sh /app/entrypoint.sh in modern Docker BuildKit to guarantee execution bits.
Contrasting OCI runtime create failed with Container exited with code 127: Both relate to missing executables, but OCI failure happens before the container process even spawns, whereas exit code 127 happens after the container started and a command inside the script was not found.