Running Scripts in a Docker Container from Windows- CR or CRLF

For Ignite 2016, I’m building out a demo for building your .NET Core code in a container. This is part of our story behind building optimized images.

But, before I get to that post, what started out as something simple, something I’ve done on my Mac fairly easily turned into a frustrating experience from Windows. It turns out sending files through the Volume Mounted wormhole can be more difficult than you might think. Not because it’s difficult in concept, but rather the errors you get are quite misleading.

Lets take a little journey:

You need to perform some tasks. Something you can easily write a script for. Lets say compiling your .NET Core code, your GoLang code, or just performing some image manipulation that requires some libraries you don’t have on your dev machine. You need to pass a collection of files to this process, and you need access to the output. The compiled app, or the watermarked, thumbnailed images.

You’ve been working with docker and think, hmmm, I can place all my dependencies in the container, and run the script in the container. But, you need the output. No problem, we can use docker volumes.

  1. From a cmd prompt:
    cd c:
    mkdir sample
    cd c:sample
    code build.sh
  2. Paste the following and save the file
    #!/bin/bash
    echo hello from a cozy container
  3. Make sure you have shared drives enabled with Docker for Windows
  4. docker run -v c:/sample:/src debian src/build.sh
    docker: Error response from daemon: oci runtime error: exec: "src/build.sh": stat src/build.sh: no such file or directory.

So, now you’re starting to question yourself.

  • Did I configure volume mounting correctly?
  • Did I get the slashes / leaning the right direction?
  • Did I get the case SenSitivItY wrong in the path?
  • Did I put the slash in the right place on -v docker side? src src
  • Was I supposed to pass .src/built.sh?

Let try something:

docker run -v c:/sample:/src debian ls /src

Yup, it’s there. Let see if we can execute the script in the container:

docker run -it -v c:/sample:/src debian bash
root@10313a424d92:/# src/build.sh
bash: ./build.sh: /bin/bash^M: bad interpreter: No such file or directory

Ahhh, our first clue Notice. the ^M: bad interpreter:
^M is aka for [CR] .

Lets try removing all those funky comments

  1. With the container still running, in VS Code, just remove #!/bin/bash and save the file.
  2. Hit the up arror and run that same src/build.sh command again
    hello from a cozy container

Voila, ok, I didn’t need that funky Linux commented thing. I didn’t like it anyway.

  1. Type exit to close the container session
  2. Lets try our original command again:
    docker run -v c:/sample:/src debian src/build.sh
    docker: Error response from daemon: oci runtime error: exec: "src/build.sh": stat src/build.sh: no such file or directory.

    Ughhhh

Windows likes Carriage Returns

This is where I just jump to the end, and save you some pain

As it turns out, Windows adds Carriage Returns and Linefeeds for each EOL. You may have remembered this. But the errors were so misleading. No such file or directory???

The simple fix – VS Code Rocks

  1. With the build.sh file open, in the bottom right of VS Code, you’ll notice:
    VSCodeCRLF
  2. Click on CRLF and notice the command palette pops up with a choice of CRLF or LF.
  3. Set to LF and save the file
  4. Try it, one more time. Call me crazy, just one more time…
    docker run -v c:/sample:/src debian src/build.sh
    standard_init_linux.go:175: exec user process caused "exec format error"
  5. Dang it
  6. Add #!/bin/bash back
  7. One last time, I promise:
    docker run -v c:/sample:/src debian src/build.sh
    echo hello from a cozy container
  8. yeahhhhhh.

So, I hope this saves you some time

If you agree that bash should default to LF, give a thumbs up to this VS Code issue

Happy wormholing,

Steve