Fixing the Docker Error: 'env: bash\r: No such file or directory'

beginner🐳 Docker2026-06-25| Docker, Windows 10/11, WSL2, Linux Containers, Git for Windows

Error Message

standard_init_linux.go:228: exec user process caused: no such file or directory (or env: 'bash\r': No such file or directory)
#docker#bash#devops#windows-tips

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.sh or setup.sh file.
  • 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.

Related Error Notes