bash 在 $PATH Dockerfile 中找不到可执行文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/50682587/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
executable file not found in $PATH Dockerfile
提问by Cassie
I am building a Dockerfile for an application. I want to execute a bash script with parameters when the container starts to run, so I have made it an entry point. However, Docker cannot find the directory in which my script is located. Thi script is located in the Intellij Idea project folder and the path practically looks like this: /home/user/Documents/folder1/folder2/folder3/Projectname/runapp.sh
我正在为应用程序构建 Dockerfile。我想在容器开始运行时执行一个带参数的 bash 脚本,所以我把它作为入口点。但是,Docker 找不到我的脚本所在的目录。此脚本位于 Intellij Idea 项目文件夹中,路径实际上如下所示:/home/user/Documents/folder1/folder2/folder3/Projectname/runapp.sh
I have tried to mount this directory as volume, but while running built image an error occurred:
我试图将此目录挂载为卷,但在运行构建映像时发生错误:
docker: Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused "exec: \"runapp.sh\": executable file not found in $PATH": unknown.
What may be the reason of such behavior? How else can I reach this bash script from Dockerfile?
这种行为的原因可能是什么?我还能如何从 Dockerfile 访问这个 bash 脚本?
Here is how the Dockerfile looks like:
这是 Dockerfile 的样子:
FROM java:8
ENV SCALA_VERSION 2.11.8
ENV SBT_VERSION 1.1.1
ENV SPARK_VERSION 2.2.0
ENV SPARK_DIST spark-$SPARK_VERSION-bin-hadoop2.6
ENV SPARK_ARCH $SPARK_DIST.tgz
ENV NEO4J_CONFIG default
ENV BENCHMARK_NAME default
WORKDIR /opt
# Install Scala
RUN \
cd /root && \
curl -o scala-$SCALA_VERSION.tgz http://downloads.typesafe.com/scala/$SCALA_VERSION/scala-$SCALA_VERSION.tgz && \
tar -xf scala-$SCALA_VERSION.tgz && \
rm scala-$SCALA_VERSION.tgz && \
echo >> /root/.bashrc && \
echo 'export PATH=~/scala-$SCALA_VERSION/bin:$PATH' >> /root/.bashrc
# Install SBT
RUN \
curl -L -o sbt-$SBT_VERSION.deb https://dl.bintray.com/sbt/debian/sbt-$SBT_VERSION.deb && \
dpkg -i sbt-$SBT_VERSION.deb && \
rm sbt-$SBT_VERSION.deb
# Install Spark
RUN \
cd /opt && \
curl -o $SPARK_ARCH http://d3kbcqa49mib13.cloudfront.net/$SPARK_ARCH && \
tar xvfz $SPARK_ARCH && \
rm $SPARK_ARCH && \
echo 'export PATH=$SPARK_DIST/bin:$PATH' >> /root/.bashrc
EXPOSE 9851 9852 4040 7474 7687 7473
VOLUME /home/user/Documents/folder1/folder2/folder3/Projectname /workdir1
WORKDIR /workdir1
ENTRYPOINT ["runapp.sh"]
CMD ["$NEO4J_CONFIG", "$BENCHMARK_NAME"]
采纳答案by gcharbon
You misunderstood volumes in Docker I think. (see What is the purpose of VOLUME in Dockerfile)
我认为您误解了 Docker 中的卷。(参见Dockerfile 中 VOLUME 的目的是什么)
I'm citing @VonC answer:
我引用@VonC 的回答:
A volume is a persistent data stored in
/var/lib/docker/volumes/...
You can either declare it in a Dockerfile, which means each time a container is stated from the image, the volume is created (empty), even if you don't have any -v option.
You can declare it on runtime
docker run -v [host-dir:]container-dir
. combining the two (VOLUME + docker run -v) means that you can mount the content of a host folder into your volume persisted by the container in/var/lib/docker/volumes/...
.
docker volume create
creates a volume without having to define a Dockerfile and build an image and run a container. It is used to quickly allow other containers to mount said volume.
卷是存储在
/var/lib/docker/volumes/...
您可以在 Dockerfile 中声明它,这意味着每次从镜像中声明一个容器时,都会创建该卷(空),即使您没有任何 -v 选项。
您可以在运行时声明它
docker run -v [host-dir:]container-dir
。将两者结合起来(VOLUME + docker run -v)意味着您可以将主机文件夹的内容安装到由/var/lib/docker/volumes/...
.
docker volume create
创建卷而无需定义 Dockerfile 并构建映像和运行容器。它用于快速允许其他容器安装所述卷。
So you should use docker run -v /home/user/Documents/folder1/folder2/folder3/Projectname:/workdir1
when starting the container
所以你应该docker run -v /home/user/Documents/folder1/folder2/folder3/Projectname:/workdir1
在启动容器时使用
And your Dockerfile volume declaration should be:
你的 Dockerfile 卷声明应该是:
VOLUME /workdir1
VOLUME /workdir1
That being said, you define both Entrypoint and CMD. What is the CMD being for ? You will never use your image without using runapp.sh
? I prefer using only CMD for development since you can still do docker run -it my_container bash
for debugging purpose with this syntax.
话虽如此,您定义了 Entrypoint 和 CMD。CMD 是干什么用的?如果不使用runapp.sh
?,您将永远不会使用您的图像。我更喜欢只使用 CMD 进行开发,因为您仍然可以docker run -it my_container bash
使用此语法进行调试。
This time I'm using @Daishi answer from What is the difference between CMD and ENTRYPOINT in a Dockerfile?
这次我使用@Daishi 回答来自Dockerfile 中的 CMD 和 ENTRYPOINT 之间的区别是什么?
The ENTRYPOINT specifies a command that will always be executed when the container starts.
The CMD specifies arguments that will be fed to the ENTRYPOINT.
If you want to make an image dedicated to a specific command you will use
ENTRYPOINT ["/path/dedicated_command"]
Otherwise, if you want to make an image for general purpose, you can leave
ENTRYPOINT
unspecified and useCMD ["/path/dedicated_command"]
as you will be able to override the setting by supplying arguments todocker run
ENTRYPOINT 指定在容器启动时将始终执行的命令。
CMD 指定将提供给 ENTRYPOINT 的参数。
如果您想制作专用于特定命令的图像,您将使用
ENTRYPOINT ["/path/dedicated_command"]
否则,如果您想为通用目的制作图像,您可以不
ENTRYPOINT
指定并使用,CMD ["/path/dedicated_command"]
因为您将能够通过提供参数来覆盖设置docker run
Moreover, runapp.sh
isn't in your $PATH
and you call it without absolute path, so it will not find the file even if the volume is mounted correctly.
You could just use:
此外,runapp.sh
不在您的目录中$PATH
并且您没有使用绝对路径调用它,因此即使正确安装了卷,它也不会找到该文件。你可以只使用:
CMD /workdir1/runapp.sh "$NEO4J_CONFIG" "$BENCHMARK_NAME"
CMD /workdir1/runapp.sh "$NEO4J_CONFIG" "$BENCHMARK_NAME"
Now be careful, on your host you mention that the shell script is named script.sh
and you call runapp.sh
in your Dockerfile, I hope it's a typo. By the way your script needs to be executable.
现在要小心,在您的主机上,您提到 shell 脚本已命名script.sh
并且您runapp.sh
在 Dockerfile 中调用,我希望这是一个错字。顺便说一下,您的脚本需要是可执行的。