【问题标题】:executable file not found in $PATH Dockerfile在 $PATH Dockerfile 中找不到可执行文件
【发布时间】:2018-06-05 14:41:39
【问题描述】:

我正在为应用程序构建 Dockerfile。我想在容器开始运行时执行一个带参数的 bash 脚本,所以我把它作为入口点。但是,Docker 找不到我的脚本所在的目录。该脚本位于 Intellij Idea 项目文件夹中,路径实际上如下所示:/home/user/Documents/folder1/folder2/folder3/Projectname/runapp.sh

我尝试将此目录挂载为卷,但在运行构建映像时发生错误:

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.

这种行为的原因可能是什么?我还能如何从 Dockerfile 访问这个 bash 脚本?

以下是 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"]

【问题讨论】:

    标签: bash docker dockerfile volume


    【解决方案1】:

    我认为你误解了 Docker 中的卷。 (见What is the purpose of VOLUME in Dockerfile)

    我引用@VonC answer:

    卷是存储在/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 并构建映像和运行容器即可创建卷。用于快速允许其他容器挂载该卷。

    所以你应该在启动容器时使用docker run -v /home/user/Documents/folder1/folder2/folder3/Projectname:/workdir1

    你的 Dockerfile 卷声明应该是:

    VOLUME /workdir1

    话虽如此,您同时定义了入口点和 CMD。 CMD 是干什么用的?如果不使用runapp.sh,您将永远不会使用您的图像?我更喜欢仅使用 CMD 进行开发,因为您仍然可以使用此语法执行 docker run -it my_container bash 进行调试。

    这次我使用@Daishi 来自What is the difference between CMD and ENTRYPOINT in a Dockerfile?的答案

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

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

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

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

    此外,runapp.sh 不在您的$PATH 中,并且您在没有绝对路径的情况下调用它,因此即使卷安装正确,它也找不到文件。 你可以使用:

    CMD /workdir1/runapp.sh "$NEO4J_CONFIG" "$BENCHMARK_NAME"

    现在请注意,在您的主机上,您提到 shell 脚本名为 script.sh,而您在 Dockerfile 中调用了 runapp.sh,我希望这是一个错字。顺便说一句,您的脚本需要是可执行的。

    【讨论】:

    • 这是一个很好的答案!你帮助理解了很多。谢谢!
    猜你喜欢
    • 2017-04-28
    • 1970-01-01
    • 2019-01-16
    • 2015-01-25
    • 2015-05-19
    • 1970-01-01
    • 2021-11-23
    • 2017-09-25
    • 2018-10-04
    相关资源
    最近更新 更多