作者:Michael Vittrup 2022-07-20 11:05:24
云计算
云原生 与脚本化 Dockerfile 相比,声明式云原生 buildpack 支持一些新场景。
为企业提供网站制作、成都做网站、网站优化、全网整合营销推广、竞价托管、品牌运营等营销获客服务。创新互联拥有网络营销运营团队,以丰富的互联网营销经验助力企业精准获客,真正落地解决中小企业营销获客难题,做到“让获客更简单”。自创立至今,成功用技术实力解决了企业“网站建设、网络品牌塑造、网络营销”三大难题,同时降低了营销成本,提高了有效客户转化率,获得了众多企业客户的高度认可!
与脚本化 Dockerfile 相比,声明式云原生 buildpack 支持一些新场景。
容器在大多数软件交付管道中无处不在,有时不是直接可见的,但它们存在于幕后。无论我们是在 Kubernetes、普通 Docker 主机、serverless functions 还是许多其他编排平台上运行软件,容器都代表了不可变的可运行软件工件。
将应用程序源代码转换为正在运行的应用程序需要一个中间容器构建阶段,而将软件转换为容器的一种非常流行的方法是通过 Dockerfile。
从 Dockerfile 构建容器是一种脚本化方法,Dockerfile 中的大部分 内容基本上是构建软件、安装依赖项等所需的命令。这也意味着学习如何使用 Dockerfile 的学习曲线很浅,并且现有构建脚本可以毫不费力地将其移植到 Dockerfile 中。
然而,事实证明,制作高质量的容器镜像并非易事。互联网上充满了制作小型、安全、最佳实践镜像的指南。通常围绕:
下面说明了一个 Dockerfile,它为 NodeJS 应用程序实现了其中的一些建议;使用两阶段构建生成一个小镜像,以非 root 身份运行,并仔细排序操作以改进缓存:
FROM node:16.13.1-alpine3.14 AS builder
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm ci
COPY tsconfig.json .
COPY src src
RUN npm run build
RUN npm prune — production
FROM node:16.13.1-alpine3.14
WORKDIR /usr/src/app
USER node
ENV NODE_ENV production
COPY — from=builder /usr/src/app/node_modules/ ./node_modules
COPY — from=builder /usr/src/app/dist/ ./dist
EXPOSE 8000
CMD [ "node", "/usr/src/app/dist/main.js" ]
编写高质量的 Dockerfile 需要相当多的努力,有时 Dockerfile 通常只是其他项目的 Dockerfile 的副本。这会导致 Dockerfile 碎片化,对于拥有多个容器的组织来说,这很快就会变得难以管理。
Buildpacks 源于这样一种想法,即对于给定类型的大多数应用程序,将应用程序源代码转换为容器或多或少是相同的。这意味着我们可以为这个过程设计可重用的程序。这个概念自 Heroku 发起并被 Cloud Foundry、Google App engine、Gitlab、CircleCI 等采用以来,已经发展超过 10 年。
社区努力确保它们提供高质量的容器镜像构建,而不是为每个应用程序使用碎片化 Dockerfiles,并具有不同级别的安全和最佳实践。
使用 buildpacks 时,我们需要了解 buildpacks 如何构建容器。与其编写脚本如何使用 Dockerfiles 构建容器,不如声明我们期望在容器中打包的内容,并让 buildpacks 找出细节。
Buildpacks 实现了许多阶段,其中两个是:
{
"engines": {
"node": "16.13.1",
"npm": "8.1.2"
},
"dependencies": {
"express": "4.17.2"
}
...
}
容器镜像携带多种形式的元数据,Buildpacks 通常使用环境变量来声明元数据设置。以下是使用环境变量设置标准org.opencontainers.description标签的示例,该标签使用Paketo image-labels buildpack在容器镜像上。环境变量的配置是通过 project.toml 文件完成的,这是声明构建配置的常用格式:
[[build.env]]
name = "BP_OCI_DESCRIPTION"
value = "Sample NodeJS from https://github.com/MichaelVL/buildpacks"
了解 Buildpacks 的这种声明性 API 对开发人员来说是必不可少的。开发人员不应该关心 Dockerfile,他们应该知道 buildpacks 的声明式 API。
Buildpacks 努力实现可重现的构建。构建过程是完全确定的,并且在使用相同的输入执行时会产生相同的输出。这使我们能够准确地验证将哪个应用程序二进制文件或源打包到容器中,并且可以保护软件交付链免受恶意应用程序被打包到容器中。
当使用 Dockerfiles 构建镜像时,容器镜像(及其哈希值 sha256 摘要)在每次重建镜像时都会发生变化,即使提供完全相同的输入也是如此。
可重现的构建是软件工件供应链级别第 4 级的要求,而 Buildpacks 是提高容器镜像供应链安全性的重要工具。
可重现的构建也是一种避免不必要的容器层重建的有效机制。
Dockerfile 中的每一行基本上都会为最终的容器镜像贡献一层。除非先前的图层发生更改,否则图层会被缓存并重用。当前面的层更改时,所有后续层都将重新构建和更改,因为 Docker 不应用可重现的构建。
使用 buildpacks,每个 buildpack 都会为容器镜像贡献一个层。如果 buildpack 的输入没有改变,则 buildpack 层不会改变,无论前面的层是否改变。此外,使用 buildpack 可以替换每个层,而不会影响其他 buildpack 生成的层。
如果需要更新容器基础镜像(例如由于安全问题),我们可以在容器镜像中重新设置该层,而无需重建任何其他应用程序层。这将很难使用基于 Dockerfile 的工作流来实现。
单层 rebase 不仅是容器镜像构建时间的显着改进,而且对于容器的部署也是如此。想象一下有 10 个服务使用某个基础镜像。如果安全问题导致我们更新此基础镜像,则基于 Dockerfile 的构建将导致重建所有镜像的所有层。这会消耗构建时间并下载完整的 10 个新镜像。使用 buildpack rebase 方法,我们只需要检索一个新的共享基础镜像。
如果使用 buildpacks 构建容器,您将遇到意想不到的时间戳:
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
sample-app latest 4713a8f7d9bb 42 years ago 202MB
这是可重现构建的副作用。为了实现可重现的构建,时间被冻结在一个固定点,以避免任何与时间相关的数据导致容器镜像差异。Buildpacks 构建具有1980 年 00:00:01 的时间戳来源的镜像,这是为了与旧文件格式的兼容而选择的。
当使用 buildpacks 构建容器时,有两个角色:
这种关注点分离对于维护多个容器镜像的组织非常有价值,因为这允许平台构建操作员控制容器镜像。例如,如果在运行镜像中发现安全问题,则可以通过更改构建器运行镜像,使用新的运行镜像重建所有容器。如上所述,这将是一个非常有效的层变基。使用 Dockerfile,这将需要更新所有应用程序 Dockerfile 中的基础镜像,并会触发所有容器镜像层的重建。
buildpacks 增强 Dockerfile 构建过程的一个示例是如何将构建相关的元数据附加到容器镜像。软件项目包含许多依赖项,并且有关这些依赖项的信息在镜像构建期间嵌入到容器镜像中。
软件物料清单 (SBOM) 是进入容器镜像的组件的结构化列表。这可用于通过将 SBOM 与已知安全问题进行比较,来确保仅使用安全软件。SBOM 还可用于验证哪个软件许可证管理软件等。CycloneDX和SPDX是结构化 SBOM 数据的两个通用标准。
下面是来自 NodeJS 项目的 SBOM 的摘录,我们可以从 SBOM 中看到所使用的 Node 引擎的确切版本,以及提供它的 buildpack:
{
{
"name": "Node Engine",
"metadata": {
"source": {
"checksum": {
"hash": "34b23965457fb0587cda6fa898e5d030211f5f374cb6"
},
"uri": "https://nodejs.org/.../node-v16.13.1.tar.gz"
},
"version": "16.13.1"
},
"buildpacks": {
"id": "paketo-buildpacks/node-engine",
"version": "0.11.2"
}
}
}
使用 SBOM 来保护软件是对使用容器镜像扫描仪的有力补充。由于 SBOM 是由 buildpacks 创建的,因此它将精确且清楚地识别交付链。容器镜像扫描仪将不得不从容器的实际内容中扣除这个版本,这将不太精确。
使用云原生 Buildpacks,构建过程和 Buildpacks 包含在两个容器镜像中:一个构建器镜像和一个运行镜像。在某种程度上,它可以被看作是一个改进的 Dockerfile 两阶段构建。下图说明了两阶段 Dockerfile 构建如何映射到 Buildpacks。请注意 NodeJS 应用程序的构建逻辑如何映射到buildpack(通常这种应用程序构建将分布在多个 buildpack 中)
构建器镜像包含一组有序的 Buildpacks 构建事物的逻辑、一个生命周期组件 Buildpacks 的编排器和对运行镜像的引用。Dockerfile 与生命周期组件没有并行性,因为 Dockerfile 是线性处理的。在检测阶段,Buildpacks 将选择加入或退出构建,生命周期组件对此进行管理。
最后,需要一个工具来触发生命周期组件:非常类似于 docker build 命令。为此,存在许多工具,其中最广为人知的是 pack 和 Tekton,然而,像 CircleCI 和 Gitlab 这样的商业持续集成供应商也支持使用 buildpacks 进行构建。
可以在此处找到使用pack 的 Github actions 工作流示例。
虽然经验丰富的 Dockerfile 作者在从 Dockerfiles 迁移到 buildpacks 时可能会感到失去了对细节的控制,但上面概述的优势有望意味着使用 buildpacks 时会以开放的心态来对待。我相信大多数开发人员都会喜欢 buildpacks。构建容器和维护 Dockerfile 从来不是他们的主要关注点,而是部署应用程序所需的必要步骤。构建平台操作员、SRE 和安全团队应该喜欢 buildpacks,因为它恢复了对容器镜像和容器镜像中内置工件的控制。
用云原生 buildpack 替换 Dockerfile 会改变我们构建容器镜像的方式:
对于开发人员和组织而言,重点关注声明性部分很重要。学习如何声明容器应该如何构建以及正在构建什么将是最重要的。
buildpacks 完美吗?
不完全是。在写这篇文章时,我尝试复制一开始提出的两阶段 Dockerfile 的精益容器构建,但是,这并不完全可行(使用 Paketo 构建器)生成的容器的大小要大一些。但是,我预计 buildpacks 会在未来改进。
还有一些应用程序很难用 buildpacks 打包到容器中。例如,如果没有自定义 Buildpacks,打包在容器(VM 风格的容器)中的遗留单体应用程序将难以实现。此类应用程序不能很好地与 buildpacks 配合使用,并且可能需要对 Dockerfile 进行低级控制,这些应用程序可能是容器打包应该注意的问题。
文章标题:七张图理解DockerfilesvsBuildpacks,二者如何选择?
网站路径:http://www.shufengxianlan.com/qtweb/news18/137068.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联