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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 16:56:00  来源:igfitidea点击:

executable file not found in $PATH Dockerfile

bashdockerdockerfilevolume

提问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 createcreates 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:/workdir1when 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 bashfor 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 ENTRYPOINTunspecified and use CMD ["/path/dedicated_command"]as you will be able to override the setting by supplying arguments to docker run

ENTRYPOINT 指定在容器启动时将始终执行的命令。

CMD 指定将提供给 ENTRYPOINT 的参数。

如果您想制作专用于特定命令的图像,您将使用 ENTRYPOINT ["/path/dedicated_command"]

否则,如果您想为通用目的制作图像,您可以不ENTRYPOINT指定并使用,CMD ["/path/dedicated_command"]因为您将能够通过提供参数来覆盖设置docker run

Moreover, runapp.shisn't in your $PATHand 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.shand you call runapp.shin your Dockerfile, I hope it's a typo. By the way your script needs to be executable.

现在要小心,在您的主机上,您提到 shell 脚本已命名script.sh并且您runapp.sh在 Dockerfile 中调用,我希望这是一个错字。顺便说一下,您的脚本需要是可执行的。