处理Docker镜像中的软件更新

比方说,我创build了一个名为foo的docker镜像,其中包含apt软件包foofoo是图像中的一个长时间运行的服务,所以图像不会经常重新启动。 什么是最好的方式去更新容器内的包?

我可以使用他们正在运行的foo版本来标记我的图像,并在容器中安装特定版本的软件包(即apt-get install foo=0.1.0并标记我的容器foo:0.1.0 ),但这意味着跟踪软件包的版本,并在每次软件包更新时创build一个新的映像/标签。 如果有办法实现自动化,我会非常高兴,但我还没有看到这样的事情。

另一种方法是在容器启动时安装(和更新)软件包,但是这意味着容器启动时的延迟会有所不同,具体取决于它是否是来自映像的新容器,或者是否启动了现有容器。 我目前正在使用这种方法,但延迟可能是相当恼人的大包。

什么(客观)最好的方式来处理这个? 不得不等待一个容器启动并更新自身并不是很理想。

如果你需要更新容器中的东西,你需要build立一个新的容器。 将容器想象成静态编译的二进制文件,就像使用C或Java一样。 你的容器内的所有东西都是一个依赖项。 如果您必须更新依赖项,请重新编译并发布新版本。

如果您在启动时篡改容器的内容,则会失去Docker的所有优点:您拥有可追踪的构build过程,并且每个容器在每个位置都可validation地完全相同,并且每次复制时都是如此。

现在我们来解释为什么你需要更新foo 。 在正常应用程序交付周期之外更新依赖项的唯一原因是修补安全漏洞。 如果你有一个CVE的通知,那么Ubuntu刚发布了一个安全补丁,那么,你必须重build每一个基于Ubuntu的容器。

有几个服务可以扫描并告诉你什么时候你的容器容易发布CVE。 例如, Quay.io和Docker Hub扫描registry中的容器。 你也可以使用克莱尔 ,奎伊在引擎盖下使用。

对于任何其他types的更新,只是不要这样做。 Docker是针对您的应用程序和运行的操作系统的100%石化策略。

因此,即使您将Docker容器复制到安装了稍微不同的库版本的1000台主机,或者将其与其他安装了不同库版本的容器一起运行,您的Docker容器也能正常工作。 即使依赖关系不能再从互联网上下载,你的容器将在2年后继续工作。

如果由于某种原因,你不能从头开始重build容器(比如它已经有2年了,所有的依赖关系都没有了),那么你可以下载容器,交互地运行它,并更新依赖关系。 在shell中执行此操作,然后将新版本的容器发回registry并重新部署。 不要在启动时这样做。