换出一层容器镜像

Vac*_*ano 6 containers docker

我想知道是否可以将容器镜像的一层换成另一层。这是我的场景:

我有一个 docker 文件,它执行以下操作:

  1. 它拉取 .net core 3.1 debian slim (buster) 镜像
  2. 构建我的应用程序的源代码并将其添加为 .net 核心映像之上的一个层

当 .net core 3.1 运行时映像的新版本出现时,我想制作一个具有该新版本但在其上具有相同应用程序层的新映像。

我不想找到我用来构建应用程序和重新构建的代码的确切版本。

这个想法是复制升级机器和运行时,但不对应用程序进行任何更改(更少测试升级)。

是否有一个 docker 命令可以用来换出图像的一层?

BMi*_*tch 1

是否可以?是的。但由于它很容易出错,因此很少有人这样做。例如,如果先前的构建已创建一个库,但该库已存在于原始基础映像中,则该库将不会包含在第一个构建中。如果基础映像删除该库,则生成的合并映像将缺少该库,因为它不在新的基础层中,也不在旧的应用程序层中。

我可以想到几种方法来做到这一点。

选项 1:如果您知道一个映像中的特定文件,则使用COPY --from语法在映像之间复制这些文件。这是最不容易出错的方法,但要求您知道要包含的每个文件。生成的 Dockerfile 如下所示:

FROM new_base

# if every file is in /usr/local/bin:
COPY --from=old_image /usr/local/bin/ /usr/local/bin/
Run Code Online (Sandbox Code Playgroud)

选项 2:您可以导出图像并通过组合两者之间的图层来创建您自己的新图像。为此,有docker savedocker load。那看起来像:

docker save old_image >old_image.tar
docker save new_base >new_base.tar
mkdir old_image new_base new_image
tar -xvf old_image.tar -C old_image
tar -xvf new_base.tar -C new_base
cp old_image/*.json new_image/
# manually: copy each layer directory you want to save from old_image, you can view the nested tar files to find the proper ones
# manually: copy each layer directory from new_base into new_image
# manually: modify the new_image/manifest.json to have the new tag for your image, and adjust the layer references
tar -cvf new_image.tar -C new_image .
docker load <new_image.tar
Run Code Online (Sandbox Code Playgroud)

选项 3:可以通过 API 调用直接向注册表完成此操作。您将拉出旧清单,使用新层对其进行调整,然后推送任何新层,然后推送新清单。这需要相当多的编码(请参阅regclient/regclient了解我如何在 Go 中实现其中一些 API)。

选项 4:我知道我见过一个在特定场景中执行此操作的工具,但我忘记了它的名称。我认为它要求您使用经过精心设计的基础映像,以减少版本之间不兼容的风险,并限制可以交换的基础映像,因此我不认为它是通用工具。

请注意,选项 2 和 3 都需要手动步骤,或者如果您想自动化,则需要编写一些代码。由于这很容易出错(如上所述),我认为您不会找到任何人维护和支持实现它的工具。绝大多数使用 CI 工具从 Dockerfile 重建。