如何在Dockerfile中运行.sh文件来启动容器?

5
我正在制作一个dockerfile来安装elasticsearch:6.5.4,并将一些文件添加到所需的位置,并运行名为test.sh的脚本,以在elasticsearch运行时创建一个新的索引。
我不确定是否应该使用RUN、CMD或ENTRYPOINT来实现这个目标。
当我注释掉最后一行(包含RUN/CMD/ENTRYPOINT test.sh)并成功构建了一个镜像并运行了容器时,我能够从容器的bash中运行test.sh并获得所需的结果。
但是,当我尝试为同样的过程构建一个镜像时,我会遇到以下错误:
$ docker build -t es .
Sending build context to Docker daemon  7.499MB
Step 1/8 : FROM elasticsearch:6.5.4
 ---> 93109ce1d590
Step 2/8 : WORKDIR /app
 ---> Running in 6b6412093d53
Removing intermediate container 6b6412093d53
 ---> a374ab69eb1a
Step 3/8 : ADD . /app
 ---> 6ed98ee7ad49
Step 4/8 : COPY test.sh .
 ---> 42184ec64c09
Step 5/8 : ADD analysis /usr/share/elasticsearch/config/analysis
 ---> 5a96f2098dd7
Step 6/8 : EXPOSE 9202
 ---> Running in 6c44b54dcc77
Removing intermediate container 6c44b54dcc77
 ---> d8723189c843
Step 7/8 : EXPOSE 9200
 ---> Running in c571b4cba1fa
Removing intermediate container c571b4cba1fa
 ---> 8fa11b03051e
Step 8/8 : RUN "sh test.sh"
 ---> Running in cf2e8cb3fd37
/bin/sh: sh test.sh: command not found
The command '/bin/sh -c "sh test.sh"' returned a non-zero code: 127

我尝试了不同的RUN、CMD和ENTRYPOINT组合来完成第8步。

我的Dockerfile如下:

FROM elasticsearch:6.5.4
WORKDIR /app
ADD . /app
COPY test.sh .
ADD analysis /usr/share/elasticsearch/config/analysis

EXPOSE 9202
EXPOSE 9200

RUN "sh test.sh"

我想在容器中运行elasticsearch,并为elasticsearch创建一个新索引。
3个回答

7
在纯机械层面上,引号会造成麻烦。当你说:
RUN "sh test.sh"

它尝试运行一个名为sh\ test.sh的单个命令;它不会尝试使用test.sh作为参数来运行sh。以下任何一种方式都可以实际运行脚本。
RUN ["sh", "test.sh"]
RUN sh test.sh
RUN chmod +x test.sh; ./test.sh

在操作层面上,您会发现在服务器容器中运行该命令非常困难。最大的问题是您需要在服务器已经启动并运行后才能运行该命令。因此,在Dockerfile中根本无法运行它(RUN命令中没有任何服务正在运行)。容器只运行一个进程,您需要将该进程设置为Elasticsearch服务器本身,因此您也不能直接在ENTRYPOINTCMD中执行此操作。

最简单的方法是从主机上运行此命令:

docker build -t my/elasticsearch .
docker run -d --name my-elasticsearch -p 9200:9200 my/elasticsearch
curl http://localhost:9200  # is it alive?
./test.sh

如果您有一个Docker Compose设置,您也可以从单独的容器中运行它,或者作为应用程序容器启动的一部分运行它。有一些很好的关于在 ENTRYPOINT 脚本中运行数据库迁移的示例,基本上这就是您要寻找的模式。
(理论上可以在entrypoint脚本中运行此操作。您必须启动服务器,等待其启动,运行脚本,停止服务器,然后最终执行exec "$@"以运行CMD。对于Elasticsearch来说,这更加棘手,因为您可能需要连接到同一Elasticsearch集群中的其他服务器,以免状态不同步。非集群数据库服务器的官方Docker Hub mysql 就是这样做的;请参阅其相当复杂的entrypoint脚本以获取想法。)

2

RUN "sh test.sh"

去掉引号。你的脚本将尝试运行名为sh test.sh的命令(带有空格)。


1
在对您的问题进行了简单的研究后,我认为您错过了一步,需要在运行实际脚本之前运行chmod +x test.sh命令,因为在容器环境中它可能不可执行。另外,我个人更喜欢使用bash来运行shell脚本。
Dockerfile:
FROM elasticsearch:6.5.4
WORKDIR /app
ADD . /app
COPY test.sh .
ADD analysis /usr/share/elasticsearch/config/analysis

EXPOSE 9202
EXPOSE 9200

RUN chmod +x test.sh
RUN bash test.sh

如果您使用 bash scriptnamesh scriptname 运行它,则无需进行 chmod。建议人们优先选择 Bash 而不是 sh 是可疑的;至少,您应该解释一下它们之间的区别。(另请参见 sh 和 bash 之间的区别 - tripleee

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