使用“gcloud build”时,Dockerfile COPY 命令缺少单个文件

Dockerfile COPY command is missing a single file when using `gcloud build`

我 运行 遇到了一个令人难以置信的令人沮丧的问题,我的 Docker 文件中的 COPY 命令成功复制了我的所有应用程序文件,只有一个除外。我没有 .dockerignore 文件,所以我知道该文件不会以这种方式从构建中排除。

注意:我确实有一个 .gitignore,它不包括我不想版本化的 file2.json。但是正如您将在下面看到的,我是从我的本地文件夹构建的,而不是从 clone/checkout 远程构建的,所以我不明白为什么 .gitignore 在这种情况下会影响 docker 构建。

下面是我的目录:

$ tree -a -I .git app
app
├── app
│   ├── data
│   │   ├── file1.txt
│   │   ├── file2.json
│   │   ├── file3.txt
│   │   └── file4.yml
│   ├── somefile2.py
│   └── somefile.py
├── Dockerfile
├── .gitignore
├── requirements.txt
└── setup.py

这就是我的 Docker 文件中的内容

FROM ubuntu:18.04
FROM python:3.7
  
COPY . /app
  
RUN cp app/app/data/file2.json ~/.somenewhiddendirectory
   
RUN pip install app/.
   
ENTRYPOINT ["python", "app/app/somefile.py"]

出于某种原因,file2.jsonCOPY . /app 调用期间未被复制,当我尝试在其他地方 cp 时出现错误。我做了一个像 RUN ls app/app/data/ 这样的调用,除了 file2.json 之外的所有文件都在那里。我检查了文件权限并确保它们与所有其他文件相同。我试过直接 COPY 那个文件,结果出错,因为 Docker 说那个文件不存在。

在我的系统上,该文件存在,我可以使用 ls 查看它,并且我可以 cat 它的内容。我一直在努力确保图像中的上下文完全位于我的应用程序的根目录中,就像我说的那样,除了 json 文件外,所有文件都已正确复制。我一辈子都想不通为什么 Docker 讨厌这个文件。

对于一些添加的上下文,我正在使用 Google 的云构建来构建图像,yaml 配置如下所示:

steps:
  - name: gcr.io/cloud-builders/docker
    id: base-image-build
    waitFor: [-]
    args:
      - build
      - .
      - -t
      - us.gcr.io/${PROJECT_ID}/base/${BRANCH_NAME}:${SHORT_SHA}
        
images:
  - us.gcr.io/${PROJECT_ID}/base/${BRANCH_NAME}:${SHORT_SHA}

我正在执行的命令如下所示:

gcloud builds submit --config=cloudbuild.yaml . \
  --substitutions=SHORT_SHA="$(git rev-parse --short HEAD)",BRANCH_NAME="$(git rev-parse --abbrev-ref HEAD)"

免责声明:我从未使用过Google的云构建,所以我的回答仅基于阅读理论。


I don't see why .gitignore would influence the docker build in this case

的确,docker build本身并不关心你的.gitignore文件。但是您正在通过 Google 的云构建进行构建,这是一个完全不同的故事。

gcloud build 命令中引用 documentation 作为源规范:

[SOURCE]
The location of the source to build. The location can be a directory on a local disk or a gzipped archive file (.tar.gz) in Google Cloud Storage. If the source is a local directory, this command skips the files specified in the --ignore-file. If --ignore-file is not specified, use .gcloudignore file. If a .gcloudignore file is absent and a .gitignore file is present in the local source directory, gcloud will use a generated Git-compatible .gcloudignore file that respects your .gitignore files. The global .gitignore is not respected. For more information on .gcloudignore, see gcloud topic gcloudignore

所以在你给定的情况下,即使从你的本地目录构建,你的文件也会被忽略。此时我看到 2 个解决此问题的选项:

  1. 删除 .gitignore 中的文件条目,这样默认的 gcloud 机制就不会在构建过程中忽略它
  2. 提供 --ignore-file 或默认值 .gcloudignore 实际上 re-includes 版本控制忽略的本地文件。

我个人会选择第二个选项,使用一些超级简单的东西,比如下面的 .gcloudignore 文件(根据 relevant documentation 制作)

.git
.gcloudignore
.gitignore