The Problem
You’ve just finished writing a perfect entrypoint.sh script on Windows. You run docker-compose up, expecting a smooth start. Instead, the container crashes immediately with a confusing error:
standard_init_linux.go:228: exec user process caused: no such file or directory
Or, if you check the logs, you might see this specific culprit:
env: 'bash\r': No such file or directory
It’s frustrating because the file is clearly there. You can see it in your folder. You can open it in your editor. So why does Docker claim it doesn't exist?
The Root Cause: Invisible Characters
The issue isn't your code; it's how your operating system saves the invisible "Enter" key at the end of each line. Windows uses CRLF (Carriage Return + Line Feed), adding two hidden characters: \r\n. Linux only uses LF (Line Feed), or \n.
When a Linux-based Docker container reads your script, it sees #!/bin/bash\r. It tries to find a program named bash\r. Since that extra \r (the Carriage Return) doesn't exist in the Linux /bin/ directory, the execution fails. Every single line in your script is essentially "polluted" by that extra 1-byte character.
How to Spot CRLF Issues
You can't see these characters in a standard text editor. To reveal them, run this command in a WSL or Linux terminal:
cat -e your-script.sh
If your terminal displays ^M$ at the end of every line, you have CRLF endings. A clean Linux-compatible file should only show a $ sign.
Fix 1: Toggle EOL in VS Code
Visual Studio Code makes this fix incredibly easy. You don't even need the command line.
- Open your
entrypoint.shorsetup.shfile. - Look at the bottom-right status bar. You’ll likely see CRLF.
- Click CRLF and select LF from the pop-up menu.
- Save the file.
Now, rebuild your image. This manual fix is perfect for quick debugging on a single file.
Fix 2: Use the dos2unix Utility
If you have dozens of scripts, changing them manually is a waste of time. Use dos2unix, a dedicated tool that strips out carriage returns in bulk.
Install it on Ubuntu or WSL with one command:
sudo apt-get install dos2unix
dos2unix script1.sh script2.sh
This utility is the gold standard for fixing line endings before you push code to a repository.
Fix 3: Automate the Fix in your Dockerfile
Relying on developers to remember to save files as LF is risky. You can build a fail-safe directly into your Dockerfile using sed. This ensures the script works even if someone clones the repo with the wrong settings.
FROM alpine:3.18
COPY entrypoint.sh /entrypoint.sh
# Force remove Windows line endings just in case
RUN sed -i 's/\r$//' /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
The sed command searches for the \r character at the end of each line and deletes it. It adds less than a second to your build time but prevents hours of headache.
Fix 4: Configure Git to Handle Line Endings
Git for Windows often converts LF to CRLF automatically during a git clone. This "helpful" feature is exactly what breaks Docker scripts. You can disable it globally or per project.
The Global Fix:
git config --global core.autocrlf input
The Better Way (.gitattributes):
Create a .gitattributes file in your project root. This forces Git to always use LF for shell scripts, regardless of the user's OS settings:
*.sh text eol=lf
Dockerfile text eol=lf
After saving this, reset your local files to apply the change:
git rm --cached -r .
git reset --hard
Final Verification
To confirm the fix worked, use the file command:
file entrypoint.sh
If the output says "Bourne-Again shell script, ASCII text executable", you are good to go. If it still mentions "with CRLF line terminators", the conversion failed. Once those hidden \r characters are gone, your Docker container will finally start as expected.

