COPY与docker但排除在外

Ale*_*lls 168 docker dockerfile docker-copy

在Dockerfile中,我有

COPY . .
Run Code Online (Sandbox Code Playgroud)

我想排除整个目录,在我的例子中,node_modules目录.

像这样的东西:

   COPY [all but **/node_modules/**] .
Run Code Online (Sandbox Code Playgroud)

Docker可以实现吗?

小智 266

.dockerignore在docker build context目录中创建文件(所以在这种情况下,很可能是node_modules的父目录),其中包含一行:

.dockerignore

虽然你可能只想要:

.dockerignore

有关dockerignore的信息:https://docs.docker.com/engine/reference/builder/#dockerignore-file

  • 如果您想将其复制但不在该层中,这并不能真正解决问题...... (46认同)
  • @SalahAdDin是的它适合你:) (12认同)
  • 只是`node_modules`在子目录中不起作用。 (7认同)
  • @PeterKionga-Kamau如果是这样的话,你能解释一下为什么`.dockerignore`文档说“这有助于避免不必要地向守护进程发送大型或敏感文件和目录,并可能使用ADD或COPY将它们添加到图像中。” 在第一段中? (7认同)
  • 这个答案从根本上来说是错误的。.dockerignore 阻止文件发送到 Docker 服务器,从而将它们从构建上下文中排除。相反,有用的是复制文件夹但不包括该文件夹的某些内容的能力。 (5认同)
  • 谢谢,所以"复制......" 我想,命令不需要改变 (3认同)
  • @SalahAdDin和你没有编写`ls/config /`的原因相同,你是否尝试将这些路径添加到你的.dockerignore而没有前导`/`? (3认同)
  • .dockerignore 与 COPY 完全无关 (3认同)
  • @ceejayoz 这不是第一次 docker 文档出错了。`.dockerignore` 确实会阻止文件发送到 **守护进程**,但如果您从本地文件夹使用 COPY,它将复制该文件夹中的所有内容,无论您在 `.dockerignore` 文件中是否有条目。您可以通过运行简单的构建轻松验证这一点 (3认同)

小智 19

对于那些无法使用.dockerignore文件的用户(例如,如果您需要在一个COPY中使用该文件,而在另一个中则不需要):

是的,但是您需要多个COPY说明。具体来说,您需要为要排除的文件名中的每个字母提供一个COPY。

COPY [^n]*    # All files that don't start with 'n'
COPY n[^o]*   # All files that start with 'n', but not 'no'
COPY no[^d]*  # All files that start with 'no', but not 'nod'
Run Code Online (Sandbox Code Playgroud)

继续直到您拥有完整的文件名或只有您有把握地确定没有其他文件的前缀为止。

  • 这不会奏效,因为当没有以“no”开头但不以“nod”开头的文件时,您将得到“复制失败:未指定源文件”。 (3认同)
  • 这对目录有效吗? (3认同)
  • 或者,您可以使用两个不同的子目录(用于不同的复制目标),例如在我的 nginx 设置中,我将 `src/` 转到 `/var/www` 和 `/conf/nginx.conf`转到“/etc/nginx/conf.d/default.conf”。另外,您可以复制所有内容,然后“RUN rm -r conf”(也保持源树原样)。我想听听是否有人有其他建议。 (2认同)
  • 如果我这样做,针对特定文件类型或文件结尾的解决方案是什么? (2认同)
  • 这种方法的唯一缺点是您的文件夹结构被扁平化 (2认同)

kta*_*kta 15

从当前目录中排除node_modules

node_modules
Run Code Online (Sandbox Code Playgroud)

排除任何直接子目录中的node_modules

*/node_modules
Run Code Online (Sandbox Code Playgroud)

这是官方文档

  • 您可以使用“**/node_modules”来完成这两项操作 (12认同)
  • @PeterKionga-Kamau 尝试了多次。今天,我重新验证了 Docker v20.10.16,并且我添加到 Dockerfile 的 COPY 或 ADD 命令不会拾取任何与 .dockerignore 条目匹配的文件。 (2认同)
  • @PeterKionga-Kamau v20.10.16 是截至 5 月 16 日的最新版本。我刚刚使用新的 dockerfile 重试了一次,并且 .dockerignore 中的所有模式/文件都没有被 COPY 或 ADD 命令拾取。你有什么时候不起作用的例子吗? (2认同)
  • @PeterKionga-Kamau 在这里:https://github.com/leonluc-dev/dockerignoreexample 构建并运行 docker 映像后,检查它应该显示 dockerignore 文件中的条目(本例中为 testfile1.txt)不是复制到docker镜像。 (2认同)

mog*_*777 11

我使用了多阶段构建方法,因为我需要一个阶段才能访问文件,但不需要另一个阶段,因此 .dockerignore 不起作用:

FROM ruby AS builder

COPY app/ app/

# Do stuff with app

# remove the stuff you don't want
RUN rm -Rf app/assets

FROM ruby AS publish

# In my real version I needed the absolute path to builder WORKDIR.
# Since I'm copying from the builder stage, app/assets won't exist
# and neither will it be part of the publish image.
COPY --from=builder app app
Run Code Online (Sandbox Code Playgroud)

  • 这是错误的。应用程序/资产仍然在图像中 - 尽管在不可见的层中。 (6认同)
  • @AndreasWittig,在多阶段构建中,仅保留您在最后阶段复制的内容。在我的示例中,我们有一个构建器阶段,它删除了一些文件。这些文件仍然存在于构建器映像上的图层中,但正如您所说,不再是该图层的一部分。当我们复制到发布阶段时,由于这些文件不可见,因此它们不会包含在发布阶段的图像中。 (3认同)
  • @jtlz2,根据https://docs.docker.com/build/building/multi-stage/,使用多阶段构建允许您从另一个阶段复制您想要的内容,并丢弃其余的内容。构建了两个映像,构建器映像具有所有膨胀,但发布映像(您将部署的映像)不会有它,因为您只是复制未删除的内容。 (3认同)

Cam*_*son 7

就我而言,我的Dockerfile包含一个安装步骤,该步骤生成vendor目录(与等效的PHP node_modules)。然后,我COPY将此目录转到最终的应用程序映像。因此,我不能把vendor我的.dockerignore。我的解决方案只是在执行之前删除目录composer install(相当于的PHP npm install)。

FROM composer AS composer
WORKDIR /app
COPY . .
RUN rm -rf composer.lock vendor \
    && composer install 

FROM richarvey/nginx-php-fpm
WORKDIR /var/www/html
COPY --from=composer /app .
Run Code Online (Sandbox Code Playgroud)

此解决方案有效且不会使最终映像膨胀,但这并不理想,因为vendor在构建过程中主机上的目录被复制到Docker上下文中,这会增加时间。


Nav*_*r V 6

对于 ONE LINER SOLUTION,在项目根目录的命令提示符终端中键入以下内容。

echo node_modules >> .dockerignore

此命令在 .dockerignore 文件中附加“node_modules”。如果 .dockerignore 不存在,它将创建一个新的。将node_modules替换为要排除的文件夹。

警告: 如果您是 Docker 生态系统的新手和/或您的项目中已经有 .dockerignore 文件,请在继续之前进行备份。

奖励:(如乔伊·巴鲁克(Joey Baruch)所指出的)

(To CREATE/OVERWRITE the .dockerignore file via PowerShell, which can be handled by Docker):
>> echo node_modules | Out-File -Encoding UTF8 .dockerignore
Run Code Online (Sandbox Code Playgroud)

  • 您真的希望人们丢失他们的 .dockerignore 内容吗?:) echo node_modules >> .dockerignore 如果是这样:) (5认同)
  • 我不知道为什么这个答案有这么多的赞成票,如果人们只是将其复制粘贴到已经有 .dockerignore 的项目中,这是很危险的。另外,如果不解释 .dockerignore 文件的功能,有人可能会认为这是 Docker 在下一个构建中不要使用该文件夹的一种方式。考虑到您回答的人通常不知道 Docker 是如何工作的。 (5认同)
  • 不要在 PowerShell 中执行此操作,它默认输出 UTF-16,我认为 docker 无法处理该问题 (3认同)
  • @NaveenKumarV 更正:如果您使用卷映射,它将映射所有内容,无论您在 .dockerignore 文件中放入什么内容。如果不使用卷映射,则可以使用 .dockerignore 将主机文件保留在映像之外。 (2认同)

Jes*_*sta 6

对于使用 gcloud build 的用户

gcloud build忽略.dockerignore并寻找.gcloudignore

使用:

cp .dockerignore .gcloudignore
Run Code Online (Sandbox Code Playgroud)

来源


Par*_*dar 5

添加 .dockerignore 对我有用。一个额外的点那些谁试图在Windows上的解决方案Windows会不会让你创建.dockerignore文件(因为它在默认情况下允许创建文件开始没有。)

要创建这样的文件以 . 在 Windows 上还包括一个结束点,例如:.dockerignore.并按 Enter(前提是您已启用文件夹选项中的视图扩展选项)

  • 您可以在 Windows 中创建一个以点开头的文件,也可以以点结尾。 (8认同)