如何在Alpine Docker容器中运行Bash脚本?

78

我有一个仅包含两个文件的目录,Dockerfilesayhello.sh

.
├── Dockerfile
└── sayhello.sh

Dockerfile 的作用是读取内容。


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

并且sayhello.sh只包含简单的内容

echo hello

Dockerfile 构建成功:

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

然而,如果我尝试运行它,我会收到一个$PATH中找不到可执行文件的错误:

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

这是什么原因呢?我记得以类似的方式在基于debian:jessie的镜像中运行脚本。也许这是专门针对Alpine的问题?

这是什么引起的?我记得以类似的方式在基于debian:jessie的镜像中运行脚本。也许这是Alpine特有的问题吗?

4个回答

126
作为默认的shell,Alpine使用ash,而不是bash

因此,您可以

  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
    

1
将Dockerfile中的CMD ["sayhello.sh"]更改为CMD ["./sayhello.sh"],问题得到了解决,无需安装Bash。 - codeforester
1
我需要在脚本顶部添加 #!/bin/ash 以便正确解释它。 - DaveO
第一点说:“在sayhello.sh文件的第一行加上一个shebang,将/bin/bash定义为解释器”,应该改成“将/bin/sh定义为解释器”吗? - Davos

40

这个答案是完全正确的,并且能够正常工作。

还有另外一种方法。您可以在基于Alpine的Docker容器中运行Bash脚本。

您需要像下面这样更改CMD:

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

这也可以运作。


8
尽管这可能有效,但Bash脚本与sh脚本不是100%的API兼容。我认为sh代表shell,而Bash代表Bourne Again SHell。因此,为了让未来的访问者知道它们是不同的Shell,请注意这一点。 - John
1
这个问题明确地寻找运行“bash”的方法,而不是“sh”。仅仅说用sh运行bash脚本并不是一个答案 - 它是一个反答案!如果那个脚本有一个只属于bash的命令怎么办? - Rene Wooller

12

记得为所有脚本授予执行权限。

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

10
如果 Dockerfile 已经具有权限,则不需要在其中授予执行权限。 - Shahriar
抱歉冒昧地问您一个问题,因为当我以那种方式终止我的Dockerfile并使用docker-compose up -d运行它时,我无法访问bash,而对于其他终止方式为CMD的容器,如php,nginx,我可以访问bash - jcarlosweb
1
@jcarlosweb 因为 Alpine 没有 bash,只有 ash。 - logoff

5
通过使用 CMD,Docker正在搜索位于 PATH 中的 sayhello.sh 文件,但是您将其复制到了不在 PATH 中的 / 目录中。
因此,请使用要执行的脚本的绝对路径:
CMD ["/sayhello.sh"]

顺便提一下,正如@user2915097所说的那样,要小心Alpine默认情况下没有Bash,如果你的脚本在shebang中使用了它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接