在需要时重建容器
Rebuilding containers when needed
一个应用容器一般由三部分组成:
- 基础映像,在 Linux 情况下,包含核心 POSIX 工具和系统库(例如
FROM debian:stable
)
- 通常从某种包安装的运行时库或帮助工具(例如
RUN apt-get update && apt-get python3-numpy && …
—对于基础 python 或 java 等。通常有一个现成的基础容器可以使用,但应用程序可能仍具有其他依赖项)。
- 同样的问题适用于链接到应用程序的依赖项(例如,由 maven 或 nuget 等引入的外部依赖项)。如果也有一个通用的解决方案来处理这个问题就好了,否则将寻求另一个特定于工具的解决方案。
- 应用程序本身(例如
COPY …/application/ /usr/local/python3.8/dist-packages/application/
并设置入口点)。
将进入生产环境的容器通常构建在构建服务器上。现在,当对应用程序进行更改时重建它是显而易见的,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.json
、yarn.lock
, Ruby 捆绑器 Gemfile.lock
, Python requirements.txt
或 Pipfile.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 的范围。
一个应用容器一般由三部分组成:
- 基础映像,在 Linux 情况下,包含核心 POSIX 工具和系统库(例如
FROM debian:stable
) - 通常从某种包安装的运行时库或帮助工具(例如
RUN apt-get update && apt-get python3-numpy && …
—对于基础 python 或 java 等。通常有一个现成的基础容器可以使用,但应用程序可能仍具有其他依赖项)。- 同样的问题适用于链接到应用程序的依赖项(例如,由 maven 或 nuget 等引入的外部依赖项)。如果也有一个通用的解决方案来处理这个问题就好了,否则将寻求另一个特定于工具的解决方案。
- 应用程序本身(例如
COPY …/application/ /usr/local/python3.8/dist-packages/application/
并设置入口点)。
将进入生产环境的容器通常构建在构建服务器上。现在,当对应用程序进行更改时重建它是显而易见的,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.json
、yarn.lock
, Ruby 捆绑器 Gemfile.lock
, Python requirements.txt
或 Pipfile.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 的范围。