Bashing Alpine

A bear, lying on its side facepalming
Photo by https://unsplash.com/@bradleyhowington

So this annoying and trivial little problem catches me out every so often. I am always misled by the error message! You'll see what I mean shortly. For context, it usually happens when I'm working in Docker containers on a build.

Let's say we have a script like this, saved as bash-script.sh:

#!/bin/bash

echo "Hello, Bash"

Nice and simple. Let's build a Docker image with it that runs it. Here's the Dockerfile.

FROM alpine

COPY bash-script.sh .

RUN ./bash-script.sh

Let's build and see what happens:

$ podman build -f bash.Dockerfile .
STEP 1: FROM alpine
STEP 2: COPY bash-script.sh .
--> 01a74a697df
STEP 3: RUN ./bash-script.sh
/bin/sh: ./bash-script.sh: not found
Error: error building at STEP "RUN ./bash-script.sh": error while running runtime: exit status 127

Aww, snap! The script has to be there, we just copied it into place. So why do we get an error saying that ./bash-script.sh is not found?

The answer is... because we're trying to run a Bash script on an Alpine image. Alpine doesn't ship with a Bash shell, so the error is really saying that the interpreter /bin/bash isn't found, not that the script itself isn't found. Catches me out every time!

The fix? #!/bin/sh instead. Might need to avoid any Bash-specific syntax. Given this script saved as sh-script.sh:

#!/bin/sh

echo "Hello, Shell"
Add in an adjusted Dockerfile to pick up the new script instead:
FROM alpine

COPY sh-script.sh .

RUN ./sh-script.sh
Building, we get:
$ podman build -f sh.Dockerfile .
STEP 1: FROM alpine
STEP 2: COPY sh-script.sh .
--> d82ae1d0b10
STEP 3: RUN ./sh-script.sh
Hello, Shell
STEP 4: COMMIT
--> 8fa27f213ed
We're all good. The #!/bin/sh directive should attempt to use a compatible shell rather than requiring Bash specifically.