将更新/升级语句放入 Dockerfile 中是一种好的做法吗?

将更新/升级语句放入 Dockerfile 中是一种好的做法吗?

我是 Docker 的新手,我正在尝试做正确的事情。

我想创建一个 docker 容器来“深度冻结”使用 bash 脚本和大量依赖项创建的应用程序,这样我就不必再对其进行维护了。我认为 docker 可以帮助我实现这一点。将更新/升级语句(如“apt-get upgrade”)放入 Dockerfile 中是一种好的做法吗?这是否会在将来潜在地破坏应用程序,而这正是 docker 应该避免的?

答案1

您想要使用更新的基础映像(其本身是由最新的软件包构建的)或自行更新(例如apt-get upgrade)的主要原因是为了获得安全修复以及其他错误修复。

您没有透露其中有什么软件,但“大量依赖项”可能意味着需要跟踪安全修复。

使用容器的总体思路是,用所需的软件构建一个最新的映像,对其进行测试,然后它在整个生命周期内保持冻结状态,并在发布新版本和部署新映像时整体丢弃。

从安全角度来看,这当然意味着定期发布。

至于您将在 Debian 中获得哪些更新的软件包(如果我们假设 Debian,从您使用 来看apt-get),他们有稳定的(即不变的)版本。即,他们不发布新版本的软件包(极少数例外),但会向其软件包版本提供修复。
这可能有助于您的“深度冻结”工作,因为行为发生变化的可能性比新版本低得多。

答案2

你是对的,apt-get upgrade将来当然会升级软件包,但你试图用它做的Dockerfile是在正确的状态下构建docker容器。docker镜像构建后,它就被冻结了,并且apt-get upgrade不再运行。

如果你重新构建了你的镜像,那么当然软件包也会更新,好吧,不要使用apt-get upgrade!你只需要运行apt-get update来刷新软件包列表。

因此您需要做的是在构建时运行apt update,然后安装您需要的每个包的特定版本:

apt-cache madison openssl
    openssl | 1.1.0f-3+deb9u2 | http://deb.debian.org/debian stretch/main amd64 Packages
   openssl | 1.1.0f-3+deb9u2 | http://security.debian.org/debian-security stretch/updates/main amd64 Packages

因此,要安装openssl 1.1.0f-3+deb9u2,请执行 apt-get install openssl=1.1.0f-3+deb9u2

您需要对每个需要特定版本的包执行此操作。

另一种方法可能是apt-get update根本不运行,但对于 Debian,软件包会因为安全问题而升级,然后在常规发行版站点上不再可用,因此这可能会docker build在将来破坏您的程序。根据脚本的构建方式和所需的依赖项,它可能值得一试。由于构建映像不需要任何成本(比磁盘空间多),请尝试两者!

答案3

如果您想运行,apt则需要更新,因为在 Docker 初始化时它的存储库是空的。

至于升级,如果您真的想“深度冻结”它,我不会建议您这样做。最好的办法是先安装apt update,然后安装依赖项的特定版本,这样您就不会在将来的某个时候获取不兼容的版本。

除此之外 - 是的,apt当您的应用程序具有不需要在其自己的容器中的依赖项时,在容器中运行是完全正常的。

答案4

正如其他人提到的,更新是必要的,因为它会检索安装软件包所需的存储库详细信息。Docker 映像通常不附带此缓存以节省磁盘空间。如果有,它很快就会过时,您需要运行新的更新。

只有当您的基础映像附带较旧的软件包时才需要升级。您不应该运行升级,而应该重建基础映像,或使用较新的软件包提取该基础映像的新版本。这不仅会让您获得已应用于上游映像的更新,而且还会减小映像大小,因为您不需要软件包的旧版本和新版本(docker 分层文件系统不会完全删除父映像中替换或删除的文件)。

为了稳定起见,我看到两种选择:

  1. 使用语法安装特定版本的软件包pkg=ver。您可能希望对特定软件包执行此操作,同时让其余软件包安装最新版本。如果您这样做,我建议将软件包版本作为构建参数传入,以便轻松更新。

  2. 安装所有内容的最新版本,但始终对图像进行版本控制,以便在出现问题时可以返回到之前的图像标签。

通常,您最终会同时执行这两项操作,但对于 #1 来说,最大的风险是忘记更新到具有安全性和错误修复的新版本。

相关内容