How do I run a Bash script in an Alpine Docker container?

81,657

Solution 1

Alpine comes with ash as the default shell instead of bash.

So you can

  1. Have a shebang defining /bin/bash as the first line of your sayhello.sh, so your file sayhello.sh will begin with bin/sh

    #!/bin/sh
    
  2. Install Bash in your Alpine image, as you seem to expect Bash is present, with such a line in your Dockerfile:

    RUN apk add --no-cache --upgrade bash
    

Solution 2

This answer is completely right and works fine.

There is another way. You can run a Bash script in an Alpine-based Docker container.

You need to change CMD like below:

CMD ["sh", "sayhello.sh"]

And this works too.

Solution 3

Remember to grant execution permission for all scripts.

FROM alpine
COPY sayhello.sh /sayhello.sh
RUN chmod +x /sayhello.sh
CMD ["/sayhello.sh"]

Solution 4

By using the CMD, Docker is searching the sayhello.sh file in the PATH, BUT you copied it in / which is not in the PATH.

So use an absolute path to the script you want to execute:

CMD ["/sayhello.sh"]

BTW, as @user2915097 said, be careful that Alpine doesn't have Bash by default in case of your script using it in the shebang.

Share:
81,657
Kurt Peek
Author by

Kurt Peek

Hi, I'm Kurt Peek, a backend engineer at Apple.

Updated on January 25, 2021

Comments

  • Kurt Peek
    Kurt Peek over 3 years

    I have a directory containing only two files, Dockerfile and sayhello.sh:

    .
    ├── Dockerfile
    └── sayhello.sh
    

    The Dockerfile reads

    FROM alpine
    COPY sayhello.sh sayhello.sh
    CMD ["sayhello.sh"]
    

    and sayhello.sh contains simply

    echo hello
    

    The Dockerfile builds successfully:

    kurtpeek@Sophiemaries-MacBook-Pro ~/d/s/trybash> docker build --tag trybash .
    Sending build context to Docker daemon 3.072 kB
    Step 1/3 : FROM alpine
     ---> 665ffb03bfae
    Step 2/3 : COPY sayhello.sh sayhello.sh
     ---> Using cache
     ---> fe41f2497715
    Step 3/3 : CMD sayhello.sh
     ---> Using cache
     ---> dfcc26c78541
    Successfully built dfcc26c78541
    

    However, if I try to run it I get an executable file not found in $PATH error:

    kurtpeek@Sophiemaries-MacBook-Pro ~/d/s/trybash> docker run trybash
    container_linux.go:247: starting container process caused "exec: \"sayhello.sh\": executable file not found in $PATH"
    docker: Error response from daemon: oci runtime error: container_linux.go:247: starting container process caused "exec: \"sayhello.sh\": executable file not found in $PATH".
    ERRO[0001] error getting events from daemon: net/http: request canceled
    

    What is causing this? I recall running scripts in debian:jessie-based images in a similar manner. So perhaps it is Alpine-specific?

  • Shahriar
    Shahriar over 6 years
    grant execution permission is not required in Dockerfile if it has permission already
  • John
    John almost 4 years
    Though this may work bash scripts are not 100% API compatible with sh scripts. sh I believe stands for shell where as Bash stands for Bourne Again SHell. gnu.org/software/bash/manual/html_node/… So just so future visitors know they really are different shells.
  • codeforester
    codeforester over 3 years
    Changing CMD ["sayhello.sh"] to CMD ["./sayhello.sh"] in Dockerfile solved the problem for me, without the need for installing Bash.
  • jcarlosweb
    jcarlosweb over 3 years
    Excuse my boldness in asking you a question, because when I terminate my Dockerfile that way, and I have run it with docker-compose up -d, I can't access the bash, while with other containers like php, nginx that terminate with CMD, I can access the bash.
  • logoff
    logoff about 3 years
    @jcarlosweb because Alpine ships no bash, only ash
  • DaveO
    DaveO almost 3 years
    I needed to add #!/bin/ash to the top of the script to have it interpreted correctly
  • Rene Wooller
    Rene Wooller over 2 years
    The question is explicitly looking for a way to run "bash", not "sh". Just saying run the bash script using sh is not an answer - it's an anti-answer! What if that script has a command unique to bash?