在$PATH Dockerfile中找不到可执行文件。

3
我正在为一个应用程序构建 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"]
1个回答

2
我觉得你对Docker中的卷有误解(参见Dockerfile中VOLUME的目的)。我引用了@VonC的回答
卷是存储在/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
话虽如此,你定义了Entrypoint和CMD。CMD是用来做什么的?你永远不会使用runapp.sh之外的镜像吗?我更喜欢只在开发时使用CMD,因为你仍然可以使用这种语法进行调试:docker run -it my_container bash
这次我引用了Dockerfile中CMD和ENTRYPOINT的区别是什么?中@Daishi的回答:
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"

现在请注意,在您的主机上,您提到脚本的名称为script.sh,并在Dockerfile中调用runapp.sh,我希望这是一个打字错误。另外,您的脚本需要可执行权限。


这是一个很好的答案!你帮助我理解了很多。谢谢! - Cassie

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