Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有没有一种方法可以只将更改过的文件作为新层添加到docker图像中,而不必诉诸docker提交?_Docker - Fatal编程技术网

有没有一种方法可以只将更改过的文件作为新层添加到docker图像中,而不必诉诸docker提交?

有没有一种方法可以只将更改过的文件作为新层添加到docker图像中,而不必诉诸docker提交?,docker,Docker,TL;DR 正在运行COPY/应用程序在源代码稍微过时的图像上创建一个与整个源代码一样大的新层,即使只有几个字节的更改。 有没有一种方法可以只将已更改的文件作为新层添加到此docker映像,而不必诉诸docker提交 长版本: 在将应用程序部署到生产环境时,我们需要将源代码添加到映像中。一个非常简单的Dockerfile用于此: FROM neam/dna-project-base-debian-php:0.6.0 COPY . /app 由于源代码非常庞大(1.2 GB),这使得每次部署都有

TL;DR

正在运行
COPY/应用程序
在源代码稍微过时的图像上创建一个与整个源代码一样大的新层,即使只有几个字节的更改。 有没有一种方法可以只将已更改的文件作为新层添加到此docker映像,而不必诉诸docker提交

长版本:

在将应用程序部署到生产环境时,我们需要将源代码添加到映像中。一个非常简单的Dockerfile用于此:

FROM neam/dna-project-base-debian-php:0.6.0
COPY . /app
由于源代码非常庞大(1.2 GB),这使得每次部署都有相当大的推动力:

$ docker build -f .stack.php.Dockerfile -t project/project-web-src-php:git-commit-17c279b .
Sending build context to Docker daemon 1.254 GB
Step 0 : FROM neam/dna-project-base-debian-php:0.6.0
 ---> 299c10c416fc
Step 1 : COPY . /app
 ---> 78a30802804a
Removing intermediate container 13b49c323bb6
Successfully built 78a30802804a

$ docker tag -f project/project-web-src-php:git-commit-17c279b tutum.co/project/project-web-src-php:git-commit-17c279b
$ docker login --email=tutum-project@project.com --username=project --password=******** https://tutum.co/v1
WARNING: login credentials saved in /home/dokku/.docker/config.json
Login Succeeded
$ docker push tutum.co/project/project-web-src-php:git-commit-17c279b
The push refers to a repository [tutum.co/project/project-web-src-php] (len: 1)
Sending image list
Pushing repository tutum.co/project/project-web-src-php (1 tags)
Image a604b236bcde already pushed, skipping
Image 1565e86129b8 already pushed, skipping
...
Image 71156b357f2f already pushed, skipping
Image 299c10c416fc already pushed, skipping
78a30802804a: Pushing [=========>                     ] 234.2 MB/1.254 GB
在下一次部署时,我们只想将更改后的文件添加到映像中,但在运行
COPY时要仔细观察/应用程序
在先前添加的图像之上,实际上需要我们再次推送1.2 GB的源代码,即使我们只更改了几个字节的源代码:

新Dockerfile(
.stack.php.git-commit-17c279b.Dockerfile
):

更改一些文件后,添加一些文本和代码,然后构建和推送:

$ docker build -f .stack.php.git-commit-17c279b.Dockerfile -t project/project-web-src-php:git-commit-17c279b-with-a-few-changes .
Sending build context to Docker daemon 1.225 GB
Step 0 : FROM project/project-web-src-php:git-commit-17c279b
 ---> 4dc643a45de3
Step 1 : COPY . /app
 ---> ecc7adc194c4
Removing intermediate container cb3e87c6cb7a
Successfully built ecc7adc194c4
$ docker tag -f project/project-web-src-php:git-commit-17c279b-with-a-few-changes tutum.co/project/project-web-src-php:git-commit-17c279b-with-a-few-changes
$ docker push tutum.co/project/project-web-src-php:git-commit-17c279b-with-a-few-changes
The push refers to a repository [tutum.co/project/project-web-src-php] (len: 1)
Sending image list
Pushing repository tutum.co/project/project-web-src-php (1 tags)
Image 1565e86129b8 already pushed, skipping
Image a604b236bcde already pushed, skipping
...
Image fe64bff23cf8 already pushed, skipping
Image 71156b357f2f already pushed, skipping
ecc7adc194c4: Pushing [==>                           ] 68.21 MB/1.225 GB
有一种解决方法可以实现上面描述的小层,其中包括在映像内启动rsync进程,然后使用docker commit将新内容保存为新层,但是(如该线程中所述),这是非正统的,因为映像不是从Dockerfile构建的,我们更喜欢不依赖docker提交的正统解决方案

有没有一种方法可以只将已更改的文件作为新层添加到此docker映像,而不必诉诸docker提交


Docker版本1.8.3

Docker缓存在Dockerfile中的每个层/指令上工作。在这种情况下,该层中使用的文件(构建上下文(
)中的所有内容)都会被修改,因此需要重建该层

如果代码的特定部分不经常更改,则可以考虑将这些代码添加到单独的层中,或者甚至将它们移到“基础图像”

根据您的项目,这可能需要一些计划或重组才能奏效,但可能值得一做。

事实上,这是有必要的

目前唯一可行的解决此问题的方法似乎是在推送新图像之前使用rsync分析新旧图像之间的差异,然后使用changelog输出生成包含相关更改的tar文件,随后将其复制到新图像层

这样,对于较小的更改,层大小变为几个字节或千字节,而不是每次1.2 GB

我把文档和脚本放在一起以帮助解决这个问题

最终结果如下所示:

验证基于修订版1图像标记内容的项目图像不会产生预期结果 确认后续的
复制/app
命令重新添加每个层中的所有文件,而不是仅添加已更改的文件:

docker history sample-project:revision-2
输出:

IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
4a3115eaf267        3 seconds ago       /bin/sh -c #(nop) COPY dir:61d102421e6692b677   16.78 MB
d4b30af167f4        25 seconds ago      /bin/sh -c #(nop) COPY dir:68b8f374d8731b8ad8   16.78 MB
c898fe1daa44        2 minutes ago       /bin/sh -c apt-get update && apt-get install    10.77 MB
39a8a358844a        4 months ago        /bin/sh -c #(nop) CMD ["/bin/bash"]             0 B
b1dacad9c5c9        4 months ago        /bin/sh -c #(nop) ADD file:5afd8eec1dc1e7666d   125.1 MB
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
1920e750d362        24 seconds ago      /bin/sh -c if [ -s /.files-to-remove.list ];    0 B
1267bf926729        2 minutes ago       /bin/sh -c #(nop) ADD file:5021c627243e841a45   19 B
d04a2181b62a        2 minutes ago       /bin/sh -c #(nop) ADD file:14780990c926e673f2   264 B
d4b30af167f4        7 minutes ago       /bin/sh -c #(nop) COPY dir:68b8f374d8731b8ad8   16.78 MB
c898fe1daa44        9 minutes ago       /bin/sh -c apt-get update && apt-get install    10.77 MB
39a8a358844a        4 months ago        /bin/sh -c #(nop) CMD ["/bin/bash"]             0 B
b1dacad9c5c9        4 months ago        /bin/sh -c #(nop) ADD file:5afd8eec1dc1e7666d   125.1 MB
尽管我们只添加/更改了几个字节,但所有文件都被重新添加,总图像大小增加了16.78 MB

此外,我们删除的文件未被删除

创建具有优化图层的图像 验证处理后的新图像是否具有较小尺寸的层,并进行以下更改:

docker history sample-project:revision-2-processed
输出:

IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
4a3115eaf267        3 seconds ago       /bin/sh -c #(nop) COPY dir:61d102421e6692b677   16.78 MB
d4b30af167f4        25 seconds ago      /bin/sh -c #(nop) COPY dir:68b8f374d8731b8ad8   16.78 MB
c898fe1daa44        2 minutes ago       /bin/sh -c apt-get update && apt-get install    10.77 MB
39a8a358844a        4 months ago        /bin/sh -c #(nop) CMD ["/bin/bash"]             0 B
b1dacad9c5c9        4 months ago        /bin/sh -c #(nop) ADD file:5afd8eec1dc1e7666d   125.1 MB
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
1920e750d362        24 seconds ago      /bin/sh -c if [ -s /.files-to-remove.list ];    0 B
1267bf926729        2 minutes ago       /bin/sh -c #(nop) ADD file:5021c627243e841a45   19 B
d04a2181b62a        2 minutes ago       /bin/sh -c #(nop) ADD file:14780990c926e673f2   264 B
d4b30af167f4        7 minutes ago       /bin/sh -c #(nop) COPY dir:68b8f374d8731b8ad8   16.78 MB
c898fe1daa44        9 minutes ago       /bin/sh -c apt-get update && apt-get install    10.77 MB
39a8a358844a        4 months ago        /bin/sh -c #(nop) CMD ["/bin/bash"]             0 B
b1dacad9c5c9        4 months ago        /bin/sh -c #(nop) ADD file:5afd8eec1dc1e7666d   125.1 MB
验证处理后的新图像是否包含与原始图像相同的内容:

export RESTRICT_DIFF_TO_PATH=/app
export OLD_IMAGE=sample-project:revision-2
export NEW_IMAGE=sample-project:revision-2-processed
docker-compose -f rsync-image-diff.docker-compose.yml up
输出应表明图像/标签之间没有差异。因此,示例项目:revision-2-processed标记现在可以推送和部署,从而获得相同的最终结果,但不必在电线上推送不必要的16.78M,从而加快部署周期。

我的解决方案:(来自的想法!)


如果您使用
git
而不是使用
COPY
ADD
将源代码拉到图像上,我想您会得到您想要的(因为这样图像上就会有一个现有的git存储库,
git-pull
只会带来新的/更新的文件)。@larsks谢谢,但是,当构建过程比运行git pull更复杂时,它将不会有帮助。它可以从git pull开始,但包括敏感配置指令的处理、composer/npm/etc依赖项的安装以及在源代码被标记为可以在生产级docker映像上登陆之前运行单元和验收测试。运行所有这些可能需要比首先推送源代码更长的时间,因此这不是一个有利的权衡。寻找有助于将层大小最小化到几kb的解决方案。不过,这是最好的选择,可能是我滥用git作为人工制品存储库的少数情况之一。将构建结果提交给一个单独的发布分支/repo,您的问题就变得相当容易解决了。不确定是否仍然正确,但过去对每幅图像的127层有一个硬限制。您可能想检查这是否仍然适用。@Erik,如果生成结果很小,这可能没问题,但是当生成结果经常超过1GB时,将生成结果复制到人工制品存储库会变得相当笨拙和耗时,请运行git commit-a,git push到远程,然后让docker生成环境git拉取这些更改。我还担心git如何处理文件所有权和权限。不幸的是,这需要规划和重组,因此必须被视为特定于某些项目的解决方案,而不是通用解决方案。我们尝试了这一点,但未能找到一种基于文件修改频率水平重组项目文件的好方法,我们也不希望我们的开发人员因为构建时间增加的风险而害怕修改某些目录。谢谢,但这个问题具体是关于如何做到这一点,而不使用docker Committe的疯狂说法,即这个bug不是一个优先事项(甚至据我所知是活动的)。我发现docker
export RESTRICT_DIFF_TO_PATH=/app
export OLD_IMAGE=sample-project:revision-2
export NEW_IMAGE=sample-project:revision-2-processed
docker-compose -f rsync-image-diff.docker-compose.yml up
docker rm -f uniquename 2> /dev/null
docker run --name uniquename -v ~/repo/mycode:/src ${REPO}/${IMAGE}:${BASE} rsync -ar --exclude-from '/src/.dockerignore' --delete /src/ /app/
docker commit uniquename ${REPO}/${IMAGE}:${NEW_TAG}