您是否仍然编写冗长的 Dockerfile 来描述构建容器映像所需的每个步骤?然后,构建包来拯救你!开发人员只需向他们提供应用程序,构建包发挥其魔力,并将其变成一个功能齐全的容器,准备部署在任何云上。
但魔术究竟是如何发生的呢?如果生成的容器性能不符合业务需求,该怎么办?
本文将深入探讨构建包的幕后情况,了解它们的运行方式,并提供有关优化默认设置以达到更好的性能结果的提示。
构建包将应用程序源代码转换为可运行的生产就绪容器映像。构建包为开发人员节省了时间和精力,因为无需配置映像并通过 Dockerfile 手动管理依赖项。
Heroku是2011年第一家开发构建包的公司。从那时起,许多其他公司(Cloud Foundry,Google等)都采用了这一概念。2018 年,Heroku 与 Pivotal 合作创建了云原生构建包项目,该项目涵盖了容器映像的现代标准和规范,例如 OCI 格式。该项目是云原生计算基金会(CNCF)的一部分。
我们将在本文中使用的Paketo构建包是一个由Cloud Foundry支持并由VMware赞助的开源项目。它实现了云原生构建包规范,并支持最流行的语言,包括Java。使用 Paketo 构建包生成的容器可以在任何云上运行。
构建包分两个阶段运行:检测和构建。
在检测阶段,构建包会分析源代码,寻找是否应将其应用于应用程序的指标。换句话说,根据源代码测试一组构建包,并选择第一组被认为适合代码来构建应用程序。在构建包检测到必要的指标后,它会返回创建映像所需的协定,并进入构建阶段。
在构建阶段,构建包转换代码库,满足之前编写的合同要求。它提供构建时和运行时环境,下载必要的依赖项,根据需要编译代码,并设置入口点和启动脚本。
生成器是构建容器映像所需的组件组合:
因此,一个构建器可以自动检测和构建不同的应用程序。
Paketo buildpacks 默认使用 Liberica JVM。Liberica是一个基于HotSpot的Java运行时,由OpenJDK的主要贡献者支持,并由Spring推荐。它为所有LTS版本(8,11,17)和当前版本以及Liberica Native Image Kit(NIK)提供JDK和JRE,这是一个基于GraalVM的实用程序,用于将基于JVM的应用程序转换为本机映像并加速启动。当您需要避免在 AWS 中冷启动时,本机映像非常有用。
但是构建包支持多个Java发行版,可以使用这些发行版代替默认的JVM:
如果要切换 JVM,则必须记住几个细微差别:
另一个重要的考虑因素是:构建包有助于和加速部署,但是如果您对容器性能不满意或寻求改进基本KPI(吞吐量,延迟或内存消耗),则必须自己调整JVM。有关更多详细信息,请参阅下面的配置 JVM 部分。
例如,基于OpenJ9 JVM的Eclipse OpenJ9在某些情况下可能表现出比HotSpot更好的性能,因为HotSpot带有默认设置,并且OpenJ9已经调整。添加一些简单的参数将为您提供与热点相同或更出色的性能。
让我们使用 Paketo 构建包构建一个 Java 容器。
首先,确保 Docker 已启动并运行。如果没有,请按照这些说明为您的系统安装 Docker 桌面。
下一步是安装 pack CLI,这是一个由云原生构建包维护的命令行界面,可用于处理构建包。按照指南完成适用于您的平台的安装(支持 macOS、Linux 和 Windows)。包是几个可用的工具之一。例如,Spring Boot 开发人员可以研究 Spring Boot Maven 插件或 Spring Boot Gradle 插件。
我们将使用 Paketo 示例应用程序,因此运行以下命令:
git clone && cd samples
Alternatively, utilize your own demo app.
Make Paketo Base builder the default builder:
pack config default-builder paketobuildpacks/builder:base
To build an image from source with Maven, run
pack build samples/java \\
--path java/maven --env BP_JVM_VERSION=17
Java example images should return {"status":"UP"} from the actuator health endpoint:
docker run --rm --tty --publish 8080:8080 samples/java
curl -s | jq .
It is also possible to build an image from a compiled artifact. The following archive formats are supported: executable JAR, WAR, or distribution ZIP.
To compile an executable JAR and build an image using pack, run
cd java/maven
./mvnw package
pack build samples/java \\
--path ./target/demo-0.0.1-SNAPSHOT.jar
软件供应链由用于开发和运行应用程序的众多库、工具和流程组成。通常很难跟踪软件产品中所有软件组件的来源,这增加了嵌套漏洞的风险。软件物料清单 (SBOM) 列出了用于构建软件项目的所有库依赖项。它类似于传统的物料清单,它总结了制造产品所需的原材料、零件、组件和确切数量。
SBOM 使开发人员能够监控软件组件的版本,及时集成安全补丁,并将易受攻击的库拒之门外。
构建包还使开发人员能够查看其映像的 SBOM。运行以下命令,为之前构建的示例/java 映像提取 SBOM:
pack sbom download samples/java --output-dir /tmp/samples-java-sbom
之后,您可以浏览该文件夹。SBOM 以 JSON 格式呈现。若要列出文件夹中的所有 .json 文件,请运行以下命令:
find /tmp/samples-java-sbom -name "*.json"
/tmp/samples-java-sbom/layers/sbom/launch/paketo-buildpacks_executable-jar/sbom.cdx.json
/tmp/samples-java-sbom/layers/sbom/launch/paketo-buildpacks_executable-jar/sbom.syft.json
/tmp/samples-java-sbom/layers/sbom/launch/paketo-buildpacks_spring-boot/helper/sbom.syft.json
/tmp/samples-java-sbom/layers/sbom/launch/paketo-buildpacks_spring-boot/spring-cloud-bindings/sbom.syft.json
/tmp/samples-java-sbom/layers/sbom/launch/paketo-buildpacks_bellsoft-liberica/jre/sbom.syft.json
/tmp/samples-java-sbom/layers/sbom/launch/paketo-buildpacks_bellsoft-liberica/helper/sbom.syft.json
/tmp/samples-java-sbom/layers/sbom/launch/sbom.legacy.json
/tmp/samples-java-sbom/layers/sbom/launch/paketo-buildpacks_ca-certificates/helper/sbom.syft.json
现在,您可以使用任何文本编辑器打开文件。例如,如果您安装了Visual Studio Code,请运行以下命令:
code /tmp/samples-java-sbom/layers/sbom/launch/paketo-buildpacks_bellsoft-liberica/jre/sbom.syft.json
您将获得以下输出:
{
"Artifacts": [
{
"ID": "1f2d01eeb13b5894",
"Name": "BellSoft Liberica JRE",
"Version": "17.0.6",
"Type": "UnknownPackage",
"FoundBy": "libpak",
"Locations": [
{
"Path": "buildpack.toml"
}
],
"Licenses": [
"GPL-2.0 WITH Classpath-exception-2.0"
],
"Language": "",
"CPEs": [
"cpe:2.3:a:oracle:jre:17.0.6:*:*:*:*:*:*:*"
],
"PURL": "pkg:generic/[email protected]?arch=amd64"
}
],
"Source": {
"Type": "directory",
"Target": "/layers/paketo-buildpacks_bellsoft-liberica/jre"
},
"Descriptor": {
"Name": "syft",
"Version": "0.32.0"
},
"Schema": {
"Version": "1.1.0",
"URL": ""
}
}
BellSoft Liberica Buildpack 提供了构建包中支持的 Java 版本的最新补丁更新。默认情况下,构建包使用最新的 LTS 版本。如果要使用其他 Java 版本,请使用 BP_JVM_VERSION 环境变量。例如,BP_JVM_VERSION=11 将安装最新版本的 Liberica JDK 和 JRE 11。
此外,您还可以更改 JDK 类型。构建包在构建时使用 JDK,在运行时使用 JRE。指定 BP_JVM_TYPE=JDK 选项将强制构建包在运行时使用 JDK。
BP_JVM_JLINK_ENABLED选项使用 Java 9+ 运行 jlink 工具,从而删除自定义 JRE。
如果将 Java 应用程序部署到应用程序服务器,则构建包默认使用 Apache Tomcat。您可以选择其他服务器(TomEE 或 Open Liberty)。例如,运行以下命令切换到 TomEE:
pack build samples/war -e BP_JAVA_APP_SERVER=tomee
您可以使用JAVA_TOOL_OPTIONS环境变量在运行时配置 JVM。例如,您可以配置垃圾回收、线程数、内存限制等,以达到满足特定需求的最佳性能:
docker run --rm --tty \\
--env JAVA_TOOL_OPTIONS='-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:MinHeapFreeRatio=20 -XX:MaxHeapFreeRatio=40' \\
--env BPL_JVM_THREAD_COUNT=100 \\
samples/java
如您所见,构建包是出色的自动化工具,可以节省开发人员的时间。但如果你明智地使用它们会有所帮助,否则你就有可能把一只猫放在麻袋里。我们的一般建议是定义 KPI 并相应地调整 JVM 设置。
如果您对生成的图像的大小不满意,该怎么办?毕竟,无法更改构建包使用的基本操作系统映像。一种选择是迁移到本机映像以优化资源消耗。另一种选择是手动构建容器并切换到较小的操作系统映像,例如Alpine或Alpaquita Linux。后者支持两种libc实现(优化的musl和glibc),并具有许多性能和安全性增强功能。