在需要时重建容器

Rebuilding containers when needed

一个应用容器一般由三部分组成:

将进入生产环境的容器通常构建在构建服务器上。现在,当对应用程序进行更改时重建它是显而易见的,CI 服务器旨在做什么。

但是前两个组件可能并且经常有针对它们的安全建议文件,当它们出现时,图像也应该重建并推送到集成测试,然后生产环境也应该更新或者管理员通知尽快触发

那么有什么方法或工具可以帮助我们设置合适的触发器来在基础容器或其他依赖项有更新时重建容器吗? Docker 默认是 Debian 基础映像,但如果它对此有更好的支持,我们会使用另一个发行版。

请注意,仅 运行 docker build --pull --no-cache nightly 不是解决方案,因为即使依赖项没有发生变化,它也会生成一个新容器,事实上,由于安装文件的不同时间戳而发生变化.而 运行 只是 docker build --pull 也不起作用,因为缓存在那里,但它只检查 Dockerfile 是否已更改并且实际上不检查包列表,或者缓存不存在在那里,因为它 运行 在不同的构建代理上,或者构建代理已被清理,因为它通常应该获得可靠的构建。

它可以使用任何容器生成器,不一定docker。

运行 docker build --pull --no-cache 每周一次左右是一个合理的妥协。很可能在那个时间范围内 一些 修复了 OS 级别的包,因此您将使用新图像重新启动容器以获得安全性更新,这是合理的。根据您部署到生产环境的频率,"on every production deploy" 可能也可能不是执行此操作的好时机。

如果跨环境的一致性对您很重要,请考虑使用带日期戳的 debian 映像版本 (FROM debian:stable-20200422),或者构建您自己的可存储在注册表中的基础映像.然后,您可以使用 Docker 文件 ARG 来指定日期戳,如果这样做,就永远不需要 --no-cache。 (但是,您必须手动发现当前版本。)

# Build with
#   docker build --build-arg DATE_STAMP=-20200422
# This must have a leading hyphen
ARG DATE_STAMP

FROM debian:stable${DATE_STAMP:-}

对于语言包,还要考虑到大多数包管理器都有一个 锁定文件 指定要使用的包的确切版本(NPM package-lock.jsonyarn.lock, Ruby 捆绑器 Gemfile.lock, Python requirements.txtPipfile.lock)。在这些情况下,您必须 运行 某种 "update" 操作来更新锁定文件;这样做会生成触发 CI 系统的提交和文件更改,这将使 Docker 构建缓存无效。

答案是,对于许多其他 docker 相关问题,放弃 docker 并切换到 buildah. Both the buildah bud, which is drop-in replacement for docker build, and the buildah commit,这是为了通过其他方式编写构建脚本,有一个--timestamp 强制写入清单的时间戳和新层中文件的时间戳都为指定值的选项。这似乎是工具本身唯一的不确定性;标准的确定性构建技术仍然需要应用于应用程序本身的构建,但这显然超出了 buildah 的范围。