【问题标题】:COPY failed: stat /var/lib/docker/tmp/docker-xxx : no such file or directory复制失败:stat /var/lib/docker/tmp/docker-xxx:没有这样的文件或目录
【发布时间】:2020-08-18 08:46:11
【问题描述】:

我有一个 github 操作工作流来构建 docker 映像:

name: Backend-Demo Docker Image CI
on:
  push:
    branches: [ master ]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Login to Azure Container Registry
        run: echo ${{ secrets.REGISTRY_PASSWORD }} | docker login ${{ secrets.LOGIN_SERVER_URL }} -u ${{ secrets.REGISTRY_USERNAME }} --password-stdin
      - name: Get the version
        id: vars
        run: echo ::set-output name=tag::$(echo ${GITHUB_REF:10})
      - name: Build the tagged Docker image
        run: docker build . --file backend/Dockerfile --tag backend-demo/spring-boot:v1.0

Dockerfile 是:

FROM openjdk:14-alpine
MAINTAINER example.com
RUN mkdir -p /opt/demo-0.0.1/lib
# Setting application source code working directory
WORKDIR /opt/demo-0.0.1/
COPY target/demo-0.0.1-SNAPSHOT.jar /opt/demo-0.0.1/lib/demo-0.0.1-SNAPSHOT.jar
# ADD target/demo-0.0.1-SNAPSHOT.jar /opt/demo-0.0.1/lib/

RUN sh -c 'touch demo-0.0.1-SNAPSHOT.jar'
ENTRYPOINT ["java"]
CMD ["-jar", "/opt/demo-0.0.1/lib/demo-0.0.1-SNAPSHOT.jar"]

但是当我执行这个工作流时,我在COPY 指令中遇到了这个错误:

Step 5/8 : COPY target/demo-0.0.1-SNAPSHOT.jar /opt/demo-0.0.1/lib/demo-0.0.1-SNAPSHOT.jar
COPY failed: stat /var/lib/docker/tmp/docker-builder851513197/target/demo-0.0.1-SNAPSHOT.jar: no such file or directory
##[error]Process completed with exit code 1.

我一直在检查,当我们将 Dockerfile 文件放在不同的目录中时,它看起来是一个典型的错误,就像我的指令一样:

docker build . --file backend/Dockerfile --tag backend-demo/spring-boot:v1.0

我也没有 .dockerignore 文件,我的 Dockerfile 准确地称为 Dockerfile

我尝试复制的 target/demo-0.0.1-SNAPSHOT.jar 文件存在于我的 github 存储库中 不确定上下文会发生什么,但this answer 可能是一个很好的提示?

【问题讨论】:

  • Dockerfile 是否与文件树中的target/ 目录处于同一级别?您也可以尝试使用相对路径,例如 COPY ./target/demo-0.1.1-SNAPSHOT.jar ...
  • @oli 是的,Dockerfiletarget 目录处于同一级别。我还尝试在COPY 使用相对路径但没有成功。
  • 作为调试步骤,您可以在COPY 指令上方添加RUN ls -l 以查看图像内目录的内容。

标签: docker dockerfile


【解决方案1】:

当你跑步时

docker build . --file backend/Dockerfile ...

路径参数. 成为上下文目录。 (Docker 实际上会向自己发送这个目录树的副本,这是 /var/lib/docker/tmp/... 路径的来源。)COPYADD 指令的源参数是相对于上下文目录,而不是相对于 Dockerfile。

如果你的源代码树看起来像

.
+-- backend
| \-- Dockerfile
\-- target
  \-- demo-0.0.1-SNAPSHOT.jar

与您显示的 Dockerfile 匹配。但如果你有

.
+-- backend
  +-- Dockerfile
  \-- target
    \-- demo-0.0.1-SNAPSHOT.jar

你会得到你看到的错误。

如果您不需要引用上下文目录之外的任何内容,您只需将要传递的目录更改为 docker build

COPY target/demo-0.0.1-SNAPSHOT.jar /opt/demo-0.0.1/lib/demo-0.0.1-SNAPSHOT.jar
docker build backend ...

或者,如果您确实需要复制其他内容,则需要将 COPY 路径更改为相对于最顶层目录。

COPY backend/target/demo-0.0.1-SNAPSHOT.jar /opt/demo-0.0.1/lib/demo-0.0.1-SNAPSHOT.jar
COPY common/config/demo.yml /opt/demo-0.0.1/etc/demo.yml
docker build . -f backend/Dockerfile ...

【讨论】:

    【解决方案2】:

    WORKDIR 只是告诉您从哪里执行其他命令。重要的一点是 WORKDIR 工作于 docker 目录,而不是本地/git 目录。根据您的示例,WORDIR 不会将上下文带到 /opt/ demo-0.0.1/ ,但只是在 docker 内创建一个空目录作为 /opt/demo-0.0.1/ 。为了使 dockerfile 工作,您应该在 COPY 命令中提供完整路径为 COPY /opt/demo-0.0.1/target/demo-0.0.1-SNAPSHOT.jar /opt/demo-0.0.1/lib /demo-0.0.1-SNAPSHOT.jar。确保 Dockerfile 与 /opt 目录处于同一级别。

    【讨论】:

    • 了解WORKDIR 我认为创建了空目录/opt/demo-0.0.1/。我不明白在COPY 命令中提供完整路径,因为不认为COPYsrc path 是我的文件系统?我的意思是我的文件系统中没有 /opt/demo-0-0.1 路径。您能否详细说明一下您的答案?
    • 当你运行 COPY 时,src 是 w.r.t git repo,所以这里的上下文永远是 dockerfile 所在的目录,并且这个上下文不会被 WORKDIR 改变。因此, src 应该始终包含我们要复制的文件的完整路径。并且 设置为 docker 容器,其默认上下文是 root,但可以使用 WORKDIR 进行更改。如果 WORKDIR 如上所述不存在,将创建新目录。所以 as /opt/demo-0.0.1/lib/demo-0.0.1-SNAPSHOT.jar 等于 WORKDIR /opt/demo-0.0.1/ 和 COPY src lib/demo-0.0.1-SNAPSHOT .jar
    • 你能检查一下这个gist,好吗?现在是我的Dockerfile,但不确定WORKDIR 指令应该在COPY 之前还是之后。
    • 由于您使用绝对路径作为COPY 的目的地,因此您将WORKDIR 设置为什么并不重要。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-16
    • 1970-01-01
    • 2019-08-30
    • 2019-02-27
    • 2020-08-09
    • 2019-09-06
    相关资源
    最近更新 更多