This error occurs when a shell script has Windows-style line endings (CRLF), causing Docker to interpret the shebang line literally as '#!/bin/bash\r' instead of '#!/bin/bash'. Converting the script to Unix line endings (LF) fixes the issue.
When Docker tries to execute a shell script as an entrypoint or command, it reads the shebang line (e.g., `#!/bin/bash`) to determine which interpreter to use. If the script was created or edited on Windows, it likely contains CRLF line endings (`\r\n`) instead of Unix-style LF endings (`\n`). The carriage return character (`\r`) becomes part of the interpreter path, so Docker looks for an executable literally named `/bin/bash\r` (with the carriage return embedded in the name). Since no such file exists, Docker reports it cannot find the executable in `$PATH`. This is one of the most common cross-platform Docker issues, especially when Windows developers collaborate with Linux/Mac developers, or when CI/CD pipelines clone repositories on different operating systems.
Before making changes, confirm that CRLF line endings are the issue. Check your script file:
file entrypoint.shIf it shows "CRLF line terminators" or "with CRLF", that confirms the problem. You can also inspect the raw bytes:
cat -A entrypoint.sh | head -5If you see ^M at the end of lines (representing \r), those are the problematic carriage returns.
The simplest fix is to convert the file to Unix line endings using dos2unix:
dos2unix entrypoint.shIf dos2unix is not installed:
# Ubuntu/Debian
sudo apt-get install dos2unix
# macOS (with Homebrew)
brew install dos2unix
# Alpine Linux
apk add dos2unix
# RHEL/CentOS/Fedora
sudo dnf install dos2unixIf you cannot install dos2unix, use built-in tools to remove carriage returns:
Using sed:
sed -i 's/\r$//' entrypoint.shOn macOS, the syntax is slightly different:
sed -i '' 's/\r$//' entrypoint.shUsing tr:
tr -d '\r' < entrypoint.sh > entrypoint.sh.tmp && mv entrypoint.sh.tmp entrypoint.shMost modern editors allow you to change line endings directly:
VS Code:
1. Open the file
2. Look at the bottom-right status bar where it says "CRLF"
3. Click on it and select "LF"
4. Save the file
Notepad++:
1. Open the file
2. Go to Edit > EOL Conversion > Unix (LF)
3. Save the file
JetBrains IDEs (IntelliJ, PyCharm, WebStorm):
1. Open the file
2. Go to File > Line Separators > LF - Unix and macOS
3. Save the file
Sublime Text:
1. Open the file
2. Go to View > Line Endings > Unix
3. Save the file
If you cannot control the source files, fix them during the Docker build process:
# Using sed (no additional packages needed)
COPY entrypoint.sh /app/entrypoint.sh
RUN sed -i 's/\r$//' /app/entrypoint.sh && chmod +x /app/entrypoint.sh
# Using dos2unix (Debian/Ubuntu)
RUN apt-get update && apt-get install -y --no-install-recommends dos2unix \
&& dos2unix /app/entrypoint.sh \
&& apt-get purge -y dos2unix && apt-get autoremove -y && rm -rf /var/lib/apt/lists/*
# Using dos2unix (Alpine)
RUN apk add --no-cache dos2unix \
&& dos2unix /app/entrypoint.sh \
&& apk del dos2unixPrevent this issue from recurring by telling Git to keep LF endings for shell scripts. Create or update .gitattributes in your repository root:
# Force LF line endings for shell scripts and Docker files
*.sh text eol=lf
*.bash text eol=lf
Dockerfile text eol=lf
docker-entrypoint* text eol=lf
entrypoint* text eol=lf
*.yml text eol=lf
*.yaml text eol=lfAfter adding .gitattributes, refresh existing files:
git rm --cached -r .
git reset --hardAlternatively, configure Git globally to convert CRLF to LF on commit:
git config --global core.autocrlf inputAfter fixing the line endings in your source files, rebuild the Docker image to pick up the changes:
docker build --no-cache -t your-image:tag .The --no-cache flag ensures Docker rebuilds all layers and copies the corrected files. Without this flag, Docker might use cached layers containing the old files with CRLF endings.
Why the error message looks strange: Docker is showing you exactly what it is looking for. The \r in the error message exec: "#!/bin/bash\r": executable file not found represents the literal carriage return character. The system is searching for a file named /bin/bash followed by a carriage return byte, which obviously does not exist.
Here-documents as a workaround: For simple scripts, you can avoid file-based line ending issues entirely by using Dockerfile here-documents (BuildKit feature):
# syntax=docker/dockerfile:1
COPY <<EOF /app/entrypoint.sh
#!/bin/bash
set -e
exec "$@"
EOF
RUN chmod +x /app/entrypoint.shCI/CD considerations: If your CI/CD system runs on Windows or clones with Git for Windows, configure the checkout step to preserve line endings:
# GitHub Actions
- uses: actions/checkout@v4
with:
# Prevents CRLF conversion
autocrlf: falseEditor configuration with EditorConfig: Add an .editorconfig file to enforce LF endings across all team members' editors:
[*.{sh,bash}]
end_of_line = lf
insert_final_newline = trueimage operating system "linux" cannot be used on this platform
How to fix 'image operating system linux cannot be used on this platform' in Docker
manifest unknown: manifest unknown
How to fix 'manifest unknown' in Docker
cannot open '/etc/passwd': Permission denied
How to fix 'cannot open: Permission denied' in Docker
Error response from daemon: failed to create the ipvlan port
How to fix 'failed to create the ipvlan port' in Docker
toomanyrequests: Rate exceeded for anonymous users
How to fix 'Rate exceeded for anonymous users' in Docker Hub