为非常大的docker映像构建上下文

我在我的主机上创建了几个不同的目录,因为我试图学习Docker,只是为了让我的dockerfile有条理。我刚刚运行的Dockerfile是这样的:

FROM crystal/centos
MAINTAINER crystal


ADD ./rpms/test.rpm ./rpms/
RUN yum -y --nogpgcheck localinstall /rpms/test.rpm

我的实际转速只有1gb。但是当我尝试执行sudo docker build -t="crystal/test" .时,我得到将构建上下文发送到Docker守护进程3.5 GB。在您继续构建Docker映像的过程中,还有什么我不知道的吗?当我在主机上的其他目录中构建更多映像时,内存是否在不断积累?

155572 次浏览

Docker客户端发送整个“构建上下文”;到Docker守护进程。该构建上下文(默认情况下)是Dockerfile所在的整个目录(因此是整个rpms树)。

你可以设置一个.dockerignore文件来让Docker忽略一些文件。你可能想尝试一下。

或者,你可以将你的rpms文件夹移动到你的Dockerfile上面一个目录级别,并且只有符号链接test.rpm移动到Dockerfile的目录中。


你会经常想要将__ABC0文件夹添加到.dockerignore,这是导致150MB ->5GB的差异,有些用户在这里的评论。

我通过移动Dockerfile和docker-compose来修复它。Yml到一个子文件夹,它工作得很好。显然,docker将当前文件夹发送到守护进程,我的文件夹是9gigs。

在我的情况下,当我执行错误的-f参数-没有路径到Dockerfile所在的目录

docker build --no-cache -t nginx5 -f /home/DF/Dockerfile /home/DF/ -对

docker build --no-cache -t nginx5 -f /home/DF/Dockerfile -错误

我和FreeStyler有同样的问题。然而,我是从上下文上一个目录构建的。所以-f参数是正确的,上下文是不正确的。

project
|
-------docker-dir

从docker-dir建立以下是很好的

docker build -t br_base:0.1 .

从dock-dir构建,构建上下文改变了。因此,我需要改变命令中的上下文。上下文由'给出。在上面的命令中。

项目目录中的新命令应该是

docker build -t br_base:0.1 ./base

这里的Context是由'./base'给出的

如果你有一个.dockerignore文件,构建上下文仍然很大,你可以使用银色的探索者检查什么被发送到docker构建上下文:

ag --path-to-ignore .dockerignore --files-with-matches

注意,一些**模式可能无法正常工作。

请参阅此Github问题以获得更多评论:https://github.com/moby/moby/issues/16056

更新2019

从Docker v18.06开始,有一个选项可以使用名为构建工具的新映像构建器。

它是预先与Docker捆绑在一起的,不需要安装任何东西。它向后兼容Dockerfile语法,不需要改变Dockerfile

传统Docker Build vs新Docker BuildKit

下面是一个用build目录中一个巨大的未使用的文件构建映像的例子:

遗留Docker构建:

$ time docker image build --no-cache .
Sending build context to Docker daemon  4.315GB
[...]
Successfully built c9ec5d33e12e


real    0m51.035s
user    0m7.189s
sys 0m10.712s

新Docker BuildKit:

$ time DOCKER_BUILDKIT=1 docker image build --no-cache .
[+] Building 0.1s (5/5) FINISHED
=> [internal] load build definition from Dockerfile                       0.0s
=> => transferring dockerfile: 37B                                        0.0s
=> [internal] load .dockerignore                                          0.0s
=> => transferring context: 2B                                            0.0s
[...]
=> => writing image sha256:ba5bca3a525ac97573b2e1d3cb936ad50cf8129eedfa9  0.0s


real    0m0.166s
user    0m0.034s
sys 0m0.026s

唯一的变化是DOCKER_BUILDKIT=1环境变量,时间上的差异是巨大的。

.dockerignore文件

请注意,.dockerignore文件仍然有效和有用。一些Dockerfile命令,如COPY . .,仍然会考虑到.dockerignore规则。但是构建目录中的副文件(在Dockerfile中没有引用)不再被BuildKit复制为“构建上下文”。

如果你想完全控制你的构建上下文,你也可以在没有任何上下文和COPY相关数据的情况下完全构建容器。

docker build - < Dockerfile

这样做的一个缺点是,使用这种方法,你只能在dockerfile中ADD东西引用远程URL,而不是来自本地主机的文件。

看到https://docs.docker.com/engine/reference/commandline/build/#build-with--

如果你正在创建图像和获取信息 将构建上下文发送到docker守护进程,这将花费日志时间来复制,

然后添加.dockerignore文件。它应该包括文件或目录

对于NodeJS Application,在根项目目录中添加一个.dockerignore文件,并在.dockerignore文件中添加以下内容

node_modules
dist

总结一下,如果你的Docker映像构建上下文太大,你可以做什么:

  • 确保在上下文中没有未使用的文件(未使用的文件-那些在映像构建过程中仍然不可触及的文件);
  • 将未使用的文件和/或目录添加到.dockerignore(如前面提到的在这里);
  • 确保你指定了正确的文件夹作为图像构建上下文(如前面提到的在这里);
  • 尝试使用DOCKER_BUILDKIT=1的BuildKit(如前面提到的在这里);
  • 试着将你的项目分成更小的部分,以优化构建上下文的内容;
  • 如果您有一个复杂的项目,您可能希望在构建之前在单独的文件夹中手动收集所有必要的文件,并将其用作特定映像的构建上下文。
检查构建的docker映像的好工具是dive https://github.com/wagoodman/dive < / p >

以下是官方说明书中的说明:

要分析Docker映像,只需运行带有image标签/id/digest的dive:

dive <your-image-tag>

或者如果你想建立你的图像,那么直接开始分析它:

dive build -t <some-tag> .

解决由不充分的.dockerignore排除引起的大型上下文问题的一个选项是使用以下命令:

rg -uuu --ignore-file .dockerignore --files --sort path .

哪个使用这个工具:https://github.com/BurntSushi/ripgrep

它工作得很好。