Introduction

An entrypoint script failure happens before your real application code even starts. The classic permission denied message usually means the script is not executable inside the image, but the root cause can also be Windows line endings, a missing interpreter in the shebang, or a build step that copied the script without the intended permissions.

Symptoms

  • The container exits immediately with code 126 or a similar startup failure
  • Docker logs show exec /entrypoint.sh: permission denied
  • The same script works on the host but fails in the container
  • The issue started after moving files between platforms or editing the Dockerfile

Common Causes

  • The entrypoint file does not have execute permission in the image
  • The script has CRLF line endings and the interpreter path is misread
  • The shebang references an interpreter not present in the image
  • A COPY step or bind mount replaced the executable file with a non-executable version

Step-by-Step Fix

  1. 1.Set executable permission during the image build
  2. 2.Do not rely on host filesystem state alone, especially when builds run in CI on different platforms.
dockerfile
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
  1. 1.**Use COPY --chmod when available**
  2. 2.This keeps permissions explicit in one place and avoids forgetting the chmod step later.
dockerfile
COPY --chmod=755 entrypoint.sh /entrypoint.sh
  1. 1.Check line endings and interpreter path
  2. 2.A file with CRLF endings or a bad shebang can look like a permission problem even though the real issue is execution format.
bash
file entrypoint.sh
  1. 1.Rebuild and test without host bind mounts
  2. 2.Bind-mounted files can override the correctly built script inside the image with a non-executable local copy.

Prevention

  • Set script permissions explicitly in the Dockerfile
  • Keep entrypoint scripts in LF line ending format
  • Use a valid shebang that matches the base image
  • Recheck bind mounts when a container works in CI but fails locally