Deployment 在开发期间重建映像时,如何避免冗余和时间损失?

Deployment 在开发期间重建映像时,如何避免冗余和时间损失?,deployment,continuous-integration,workflow,docker,Deployment,Continuous Integration,Workflow,Docker,作为一个流浪用户,在尝试Docker时,我注意到使用Vagrant和Docker的开发工作流之间的一个显著区别——使用Docker,我每次都需要从头开始重建我的映像,即使我对代码做了微小的更改 这对我来说是一个主要问题,因为图像重建的过程往往非常冗余和耗时 也许Docker已经发明了一些智能工作流,如果是的话,它们是什么?正如Mark O'Connor所建议的,其中一个技巧可能是为您的容器构建基础图像。此映像应具有依赖项、包安装、下载。。。或任何其他消费活动。此基础映像的创建频率应低于其他映像。

作为一个流浪用户,在尝试Docker时,我注意到使用Vagrant和Docker的开发工作流之间的一个显著区别——使用Docker,我每次都需要从头开始重建我的映像,即使我对代码做了微小的更改

这对我来说是一个主要问题,因为图像重建的过程往往非常冗余和耗时


也许Docker已经发明了一些智能工作流,如果是的话,它们是什么?

正如Mark O'Connor所建议的,其中一个技巧可能是为您的容器构建基础图像。此映像应具有依赖项、包安装、下载。。。或任何其他消费活动。此基础映像的创建频率应低于其他映像。以类似的方式,如果Docker文件每个步骤的最终执行状态没有改变,Docker就不会再次构建该层。因此,您可以尝试执行命令,但几乎每次运行(例如:apt get update)时都可能会更改此状态,因此docker不必在运行之前重新构建步骤。此外,您还可以尝试在后面的步骤中比在第一步中更好地编辑DockerFile

如果您在容器内编译/下载某些内容,另一个选项是将其下载或编译到主机文件夹中,并使用
docker run
中的
-v
-volume
选项将其附加到容器

最后,还有其他解决这个问题的方法,如chef with使用的方法。在这种方法中,您使用chef cookbooks构建容器,每次构建容器时(因为您已经编辑了cookbooks…),这些更改将作为新的docker层(AUFS层)应用,您不必重复所有过程。我不推荐这个解决方案,除非你有厨师的经验,并且你有食谱来管理你的软件。您应该更加努力地工作,以使其正常工作,如果您希望Chef只管理docker容器,我认为这是不值得的(尽管Chef是管理基础设施的一个很好的选择)

要在有多个图像依赖项的情况下自动构建过程,可以使用bash脚本来帮助您完成该任务(归功于):


我为vagrant cachier插件提交了一个功能请求,用于保存docker构建数据,并为该过程附加了一个bash解决方案。如果你可以自己动手,你可以在vagrant中实现脚本

请注意,此过程需要安装vagrant cachier插件,并且必须从磁盘保存和加载+300MB的文件(如果这些文件是计算机的新文件)。因此,如果你的DockerFile只有1-5行代码,那么它的速度会很慢,但是如果你的DockerFile有很多LOC或图片,那么它的速度会很快,这些都是必须从网上下载的

还请注意,这种方法可以节省每个中间构建步骤。因此,如果您正在构建一个图像并在DOCKFILE文件的中间更改一行并再次构建,则DOCKER构建过程将获得所有缓存的中间容器,直到更改的行。 使用baseimages仍然是首选方法,但您可以将这两种过程结合起来


请随意发布改进并订阅,这样fgrehm可能会在其插件中以本机方式实现此功能。

有一些技巧可能会改善您的工作流程(非常注重网络)

Docker缓存 始终确保在Dockerfile的最后将源添加到Docker映像中。 榜样

COPY data/package.json /data/
RUN cd /data && npm install

COPY data/ /data
这将确保您在构建映像时获得最佳缓存,并且Docker在您更改源代码时不必重建npm包

另外,请确保您没有添加经常更改的文件夹/文件的基本映像(例如基本映像执行
复制。/data/

无花果架 使用fig(或其他工具),在开发时挂载源目录。这样,您可以通过即时更改进行开发,并且在构建映像时仍然使用当前版本的代码

开发服务器 您可以在开发时启动developer web服务器,不启动时启动nginx(如果您正在开发www应用程序,但同样的想法也适用于其他应用程序)

例如,在启动脚本中,执行以下操作:

if [[ $DEBUG ]]; then
  /usr/bin/supervisorctl start gulp
else
  /usr/bin/supervisorctl start nginx
fi
并在supervisord.conf文件中设置
autostart=false

自动刷新应用程序 如果您正在开发web应用程序,请使用
gulp
和eg
gulp connect
等工具;如果您正在开发python/django应用程序,请使用runserver实用程序。检测文件中的更改时,这两种工具都会重新加载服务器


如果您使用的是
If[[$DEBUG]]…
技巧,请让他们在与普通实例(nginx)相同的端口上侦听。这样,您的反向代理可以有1个配置,即只需将流量发送到示例
www:8080
,它将在生产和开发过程中访问您的网页。

创建一个包含大部分应用程序依赖项的基于映像。这将显著减少docker的构建时间。

@MarkO'Con也不知道系统如何知道它们是否更改了?请参阅:@MarkO'Connor我正在使用Ansible构建映像,使用这样的命令
运行Ansible playbook provision.yml…
-并且它不会命中缓存。@MarkO'Connor我构建的以及Docker 1.4.1缓存如果我只更改
provision.yml
,而不更改
运行
stateme,则无效在
Dockerfile
@MarkO'Connor中输入nt,如果您发布有关缓存的答案,我将接受它。我在这里看到的主要问题是如何正确版本此依赖项映像?您询问的是哪种解决方案?如我所见,您可以尝试管理使用不同标记标记每个生成的映像之间的依赖项,将版本作为标记引用,然后在“子”Dockerfiles中更新或不更新
FROM
命令的时间。想象一下,我的image和deps以及main image都使用此dep
if [[ $DEBUG ]]; then
  /usr/bin/supervisorctl start gulp
else
  /usr/bin/supervisorctl start nginx
fi