1、简介 {#1简介}
在本教程中,我们将了解如何把使用 Spring Boot 创建的 Java 应用作为 Docker 容器运行,具体来说,我们将在 Alpaquita Linux 上使用 Liberica JDK 来创建运行我们应用的 Docker 镜像。
Liberica JDK 和 Alpaquita Linux 是 BellSoft 产品的一部分。BellSoft 的愿景是使 Java 成为云原生应用程序的首选语言。
2、简单的 Spring Boot 应用 {#2简单的-spring-boot-应用}
先用 Java 创建一个简单的应用,然后将其容器化。通过 Spring Boot,我们只需进行最少的配置,就能轻松创建基于 Spring 的独立生产级应用。
初始化 Spring Boot 应用的最简单方法是使用 Spring Boot CLI。通过它,可以在命令行中使用 start.springboot.io 创建一个新项目:
$ spring init --build=gradle --dependencies=web spring-bellsoft
如上,添加了 web
依赖,以构建 RESTful API,并将 Apache Tomcat 作为默认的嵌入式容器。选择 Gradle 作为构建工具,默认的语言是 Java。
然后,可以将生成的项目导入 IDE(如 IntelliJ Idea),开始开发应用。
添加一个简单的 REST API,接收一个 Integer
参数,并返回等于或小于该数字的斐波纳契数列:
@RestController
public class DemoController {
@GetMapping("/api/v1/fibs")
public List<Integer> getFibonacciSeriesBelowGivenInteger(Integer input) {
List<Integer> result;
if (input == 0)
result = List.of(0);
else {
int n = 0; int m = 1;
result = new ArrayList<>(Arrays.asList(n));
while (m <= input) {
result.add(m);
m = n + m; n = m - n;
}
}
return result;
}
}
在 Gradle 中构建应用非常简单,只需运行以下命令即可:
# 使用了生成的 Gradle Wrapper
./gradlew clean build
生成项目的默认打包方式是 JAR,上述命令成功执行后,将在输出目录 ./build/libs
中创建最终可执行 JAR。
运行该 JAR,启动应用:
java -jar ./build/libs/spring-bellsoft-0.0.1-SNAPSHOT.jar
然后,调用 API,看看它是否运行正常:
$ curl http://localhost:8080/api/v1/fibs?input=5
[0,1,1,2,3,5]
这就是本教程将会使用到的一个超级简单的应用。
3、容器化 {#3容器化}
容器是一种标准的软件单元,它将代码和所有依赖项打包在一起。它是一种操作系统虚拟化的形式,提供了一种一致的部署应用程序的方式。如今,在云环境中运行任何应用程序时,容器已成为默认选择。
我们需要一个容器平台来将我们的应用作为容器运行。容器平台除其他功能外,还提供用于创建和管理容器的容器引擎。Docker 是最流行的平台,旨在构建、共享和运行容器应用程序。
容器引擎从容器镜像创建容器。容器镜像是一个不可变的静态文件,包含容器运行所需的一切。然而,它共享主机的操作系统内核。因此,它提供了完全的隔离性,但仍然是轻量级的。
创建 Docker 镜像的一种方式是将创建镜像的步骤描述为 Dockerfile。然后,可以使用 Docker 守护进程根据 Dockerfile 创建镜像。Docker 的原始镜像格式现在已成为 开放容器倡议(OCI)镜像规范。
将应用作为容器运行的一个核心的优势是,在多个环境中提供一致的部署体验。例如,假设我们使用 Java 17 构建了一个简单的应用,但需要在一个只有 Java 11 运行时的环境中进行部署。
为了避免这种意外情况,容器镜像允许我们打包应用程序的所有关键依赖,例如操作系统的二进制文件/库和 Java 运行时环境。通过这样做,我们可以确保无论应用程序在哪个环境中部署,它的行为都是一致的。
4、Liberica Runtime 容器 {#4liberica-runtime-容器}
一个容器镜像由多个相互叠加的 "层" 组成。每个层代表对文件系统的特定修改。通常,我们从一个最符合应用要求的基础镜像开始,并在其之上构建额外的层。
BellSoft 提供了几个针对在云环境中运行 Java 应用程序进行高度优化的镜像。它们使用了 Alpaquita Linux 和 Liberica JDK 进行构建。在使用这些镜像之前,让我们来看一下它们的的优点。
4.1、Alpaquita Linux 的优势 {#41alpaquita-linux-的优势}
Alpaquita Linux 是基于 Alpine Linux 的轻量级操作系统。它专为 Java 量身定制,并针对云原生应用程序的部署进行了优化。它的基本镜像大小为 3.22 MB,运行时只需少量资源。
Alpaquita Linux 有两个版本,一个基于优化的 musl libc,另一个基于 glib libc。这里的 libc 是指 ISO C 标准中规定的 C 语言标准库。它为多项任务提供宏、类型定义和函数。
除了针对 Java 应用程序进行优化外,Alpaquita Linux 还为我们的部署提供了多项安全功能。这些功能包括网络功能、自定义构建选项和进程隔离。它还包括内核锁定和内核模块签名等内核加固功能。
此外,Alpaquita Linux 经过优化以便于部署,它使用内核模块压缩来减小软件包的大小。它提供了可靠且高效的堆栈,具备内核优化和内存管理等性能特性,可用于运行应用程序。
Alpaquita Linux 只打包了少量操作系统组件。不过,我们可以从 Alpaquita APK Repository 中安装额外的模块和附加软件包。最重要的是,Alpaquita Linux 的 LTS 版本支持周期为四年。
4.2、Liberica JDK 的优势 {#42liberica-jdk-的优势}
Liberica JDK 是用于现代 Java 部署的开源 Java 运行时。它由 OpenJDK 的主要贡献者 BellSoft 提供,承诺为 Java 应用程序提供适用于云、服务器和桌面的单一运行时。它还推荐用于基于 Spring 的 Java 应用程序。
Liberica JDK 支持各种架构,如 x86 64/32位、ARM、PowerPC 和 SPARC。它还支持多种操作系统,如 Windows、macOS 和大多数 Linux 发行版。此外,它还支持目前使用的几乎所有 Java 版本。
Liberica JDK 的关键优势之一是非常轻量级。基于 Alpaquita Linux for Java 17 的 Liberica 运行时容器不到 70 MB。它承诺在降低流量、存储、内存消耗和总成本的同时提供更好的性能。
它还具有多种工具,可与 JDK 运行时配合使用。用户可以访问用于监控和更新的工具。此外,用户还可以访问 Liberica 管理中心(LAC),这是一个用于运行时监控、许可证控制和安全更新的企业工具。
Liberica JDK 已通过 Java SE 规范的 TCK 验证,并在每个发布之前经过全面测试以确保其稳定性。此外,BellSoft 保证提供至少八年的 Liberica JDK 生命周期支持,包括错误修复、安全补丁和其他必要的改进。
5、创建容器镜像 {#5创建容器镜像}
现在,我们准备使用 Alpaquita Linux 和 Liberica JDK 对我们的应用进行容器化。第一步是选择一个包含这些依赖项的基础镜像。虽然,我们可以创建自己的基础镜像,但 BellSoft 在 Docker Hub 上维护了多个镜像 供我们选择。
5.1、选择 Liberica 运行时容器 {#51选择-liberica-运行时容器}
Alpaquita Linux 镜像,提供了不同选项的 Liberica JDK Lite 和 Liberica JRE 供选择。通常,我们可以通过标签来识别,标签可能包含以下之一:
- jdk:带有 Liberica JDK Lite 版本的 Alpaquita Linux 镜像
- jdk-all:Liberica JDK 包,可用于使用 jlink 工具创建自定义运行时
- jre:仅包含用于运行 Java 应用的 Liberica JRE
镜像的标签除了包含 JDK 版本之外,还有关于镜像的其他信息。让我们来看一下 BellSoft 使用的镜像标签约定:
[JDK type]-Java version-[slim]-[OS release]-[libc type]-[date]
标签的不同部分告诉我们镜像的特定方面,用于帮助我们从众多可用的镜像中选择合适的镜像:
- JDK type:JDK 的类型(JDK、jdk-all 和 jre,如前所述)
- Java version:JDK 所符合的 Java 版本
- slim:表示镜像是否是精简版的
- OS version:操作系统的版本(目前只有
stream
) - libc type:标准 C 语言库的类型(如前所述,是 glibc 还是 musl)
- date:镜像的发布日期
5.2、将应用容器化 {#52将应用容器化}
现在,选择一个合适的镜像。例如,如果我们想要使用带有 glibc 的 Java 17 作为我们的应用程序,我们需要选择标签为 "jdk-17-glibc" 的镜像。
选择好了基础镜像标签,下一步就是创建一个 Dockerfile,以定义如何为我们的应用创建容器镜像:
FROM bellsoft/liberica-runtime-container:jdk-17-glibc
VOLUME /tmp
ARG JAR_FILE=build/libs/java-bellsoft-0.0.1-SNAPSHOT.jar
${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
这个相当简单的 Dockerfile 表明我们希望从 Liberica 运行时容器和我们的应用程序 Fat JAR 开始。还定义了 ENTRYPOINT
,并提供了在容器启动后运行我们的应用程序的指令。
我们应该把这个 Dockerfile 放在应用程序代码库目录的根目录下。然后,可以使用以下命令在本地仓库中创建容器镜像:
docker buildx build -t spring-bellsoft .
默认情况下,这将从注册中心 Docker Hub 拉取基础镜像,并为我们的应用创建容器镜像。然后,我们可以将该镜像作为容器运行:
docker run --name fibonacci -d -p 8080:8080 spring-bellsoft
注意,我们已将本地端口 8080
与容器端口 8080
进行了映射。因此,我们可以像本文前面那样访问我们的应用:
$ curl http://localhost:8080/api/v1/fibs?input=5
[0,1,1,2,3,5]
至此,我们成功地使用 BellSoft 发布的 Liberica 运行时容器对本文前面创建的应用进行容器化。
6、总结 {#6总结}
本文介绍了为 Spring Boot 应用创建 BellSoft Liberica 运行时容器的基础知识,还了解了作为 Liberica 运行时容器组成部分的 Alpaquita Linux 和 Liberica JDK 的优势。
参考:https://www.baeldung.com/spring-docker-liberica