如何使用 Dockerfile 在一层中复制多个文件?

Posted

技术标签:

【中文标题】如何使用 Dockerfile 在一层中复制多个文件?【英文标题】:How to copy multiple files in one layer using a Dockerfile? 【发布时间】:2015-07-27 04:39:36 【问题描述】:

以下Dockerfile 包含四个COPY 层:

COPY README.md ./
COPY package.json ./
COPY gulpfile.js ./
COPY __BUILD_NUMBER ./

如何使用一层来复制这些文件?尝试了以下方法:

COPY [
    "__BUILD_NUMBER ./",
    "README.md ./",
    "gulpfile ./",
    "another_file ./",
]

【问题讨论】:

【参考方案1】:
COPY README.md package.json gulpfile.js __BUILD_NUMBER ./

COPY ["__BUILD_NUMBER", "README.md", "gulpfile", "another_file", "./"]

您还可以在源文件规范中使用通配符。 See the docs for a little more detail.

目录很特别!如果你写

COPY dir1 dir2 ./

实际上是这样的

COPY dir1/* dir2/* ./

如果您想在单个命令中复制目标目录下的多个目录(不是它们的内容),您需要设置构建上下文,以便您的源目录位于一个共同的父目录下,然后 COPY父母。

【讨论】:

请注意,如果源是目录,这会复制目录 contents,而不是目录本身。 还要注意目标目录是相同的。如果您使用不同的目的地处理大量不同的文件,那么您可能需要考虑构建一个覆盖文件系统(如 chroot),然后将其转换为 tar 存档,并使用 ADD 添加它。 @Claudiu 如何自己复制文件夹? @k0pernikus 你可以说 COPY myDir1 ./MyDir1/ @manuel-manhart 有没有人知道我们是否可以使用构建参数参数化文件列表? github.com/moby/moby/issues/38532?【参考方案2】:
COPY <all> <the> <things> <last-arg-is-destination>

但这里有一个重要的文档摘录:

如果您有多个使用不同文件的 Dockerfile 步骤 您的上下文,单独复制它们,而不是一次全部复制。这 确保每个步骤的构建缓存仅失效(强制 如果特别需要的文件发生更改,则重新运行步骤。

https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#add-or-copy

【讨论】:

你知道我们是否可以参数化“所有的东西”吗???使用构建参数? github.com/moby/moby/issues/38532??? @MarcellodeSales 不确定您为什么需要它。为什么不创建一个没有这些文件的基础图像,然后子图像中包含复制指令 - 如果他们需要定义路径,无论如何它并没有太大的区别。或者您可以将其完全保留在图像之外并将其挂载到容器中 - 您可以使用 .env 文件进行配置。 此外,您始终可以在现有路径上进行复制,因为文件系统是分层的,它会覆盖/隐藏预先存在的内容。 @ManuelManhart,我正在使用 ONBUILD COPY 构建动态参数化图像...作为平台的一部分,我隐藏了需要在图像中完成的操作的复杂性,所以,那就是为什么我需要将这些值作为参数提供。 @MarcellodeSales 我认为现在/尚未支持此功能。但是您可以使用构建参数对其进行封装,请参阅***.com/questions/43654656/…【参考方案3】:

值得一提的是,您还可以创建一个.dockerignore 文件,以排除您不想想要复制的文件和目录:

https://docs.docker.com/engine/reference/builder/#dockerignore-file

在 docker CLI 将上下文发送到 docker 守护进程之前,它会在上下文的根目录中查找名为 .dockerignore 的文件。如果此文件存在,CLI 会修改上下文以排除与其中的模式匹配的文件和目录。这有助于避免不必要地将大型或敏感文件和目录发送到守护程序,并可能使用 ADD 或 COPY 将它们添加到图像中。

【讨论】:

【参考方案4】:

简单

COPY README.md  package.json gulpfile.js __BUILD_NUMBER ./

来自doc

如果指定了多个资源,直接或由于 使用通配符,则必须是目录,并且必须 以斜杠 / 结尾。

【讨论】:

【参考方案5】:

原始答案警告异常处理目录。 https://***.com/a/30316600/3257491

如果您想通过只包含一个或多个目录以及零个或多个特定文件的目录来实现这一点,您可以使用.dockerignore

.dockerignore 文件忽略除src 目录、test 目录package.json 文件和package-lock.json 文件之外的所有内容:

*
!src
!test
!package.json
!package-lock.json

然后Dockerfile:

COPY . ./

这将仅包括 .dockerignore 文件中的异常中包含的文件。

【讨论】:

【参考方案6】:

为了便于查看,您可能需要多行 COPY 命令。例如。要复制的文件列表很长。

反斜杠转义行尾的处理方式如下:

COPY __BUILD_NUMBER    \
     README.md         \
     gulpfile          \
     another_file      \
     ./

我可以为RUN 命令找到一个example with backslash,但对于COPY 却找不到。它也适用于COPY

【讨论】:

以上是关于如何使用 Dockerfile 在一层中复制多个文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 TensorFlow 在一层中创建并行线性计算?

Docker容器之镜像管理端口映射容器互联

Docker容器之镜像管理,端口映射,容器互联

Dockerfile指令

如何使用Dockerfile中的单个COPY层复制不同源和目标目录中的多个文件

在一层上绘制多个 UIView