假设我创建了一个名为foo
的docker镜像,其中包含apt包foo
。 foo
是图像中长时间运行的服务,因此图像不会经常重启。更新容器内的包的最佳方法是什么?
我可以使用他们正在运行的foo
版本标记我的图片,并在容器内安装特定版本的包(即apt-get install foo=0.1.0
并标记我的容器foo:0.1.0
)但这意味着每次包更新时都要跟踪包的版本并创建新的图像/标签。如果有一些方法可以实现自动化,我会对此非常满意,但我还没有看到这样的东西。
另一种方法是在容器启动时安装(和更新)包,但这意味着容器启动时会有不同的延迟,具体取决于它是图像中的新容器还是我们正在启动现有容器。我目前正在使用这种方法,但对于更大的包,延迟可能会相当烦人。
处理此问题的(客观)最佳方法是什么?等待容器启动并自行更新并不是很理想。
答案 0 :(得分:4)
如果您需要更新容器中的内容,则需要构建一个新容器。将容器视为静态编译的二进制文件,就像使用C或Java一样。容器内的所有内容都是依赖项。如果必须更新依赖项,则重新编译并发布新版本。
如果你在启动时篡改了容器的内容,你将失去Docker的所有好处:你有一个可跟踪的构建过程,并且每个容器在每个地方和每次复制时都是可以逐位相同的。 / p>
现在让我们解决为什么你需要更新foo
。您应该在正常的应用程序交付周期之外更新依赖关系的唯一原因是修补安全漏洞。如果你有一个CVE通知说ubuntu刚刚发布了一个安全补丁,那么,你必须重建基于ubuntu的每个容器。
当您的容器容易受到已发布的CVE攻击时,有几种服务会扫描并告诉您。例如,Quay.io和Docker Hub扫描注册表中的容器。您也可以使用Quay在引擎盖下使用的Clair自己完成此操作。
对于任何其他类型的更新,请不要这样做。 Docker是针对您的应用程序及其运行的操作系统的100%僵化策略。
因此,即使您将Docker容器复制到安装了稍微不同的库版本的1000个主机,也可以将其运行,或者将其与安装了不同库版本的其他容器一起运行。即使无法再从互联网上下载依赖项,您的容器将在2年后继续工作。
如果由于某种原因你无法从头开始重建容器(例如它已经2年了,并且所有依赖项都丢失了)那么是的,你可以下载容器,以交互方式运行它,并更新依赖项。在shell中执行此操作,然后将新版本的容器发布回注册表并重新部署。不要在启动时这样做。