Dockerfiles
虽然只需在 Dockerfile
中写几行就能将 Spring Boot uber jar 转换为 Docker 镜像,但使用 分层特性 能获得更优的镜像。
当你创建包含 layers 索引文件的 jar 时,spring-boot-jarmode-tools
jar 会作为依赖添加到你的 jar 中。
有了这个 jar 在类路径上,你可以以特殊模式启动应用,让引导代码运行与应用本身完全不同的内容,例如提取分层。
带有启动脚本的 完全可执行 Spring Boot 存档 不支持 tools 模式。
构建用于 extract tools 模式命令的 jar 文件时,请禁用启动脚本配置。
|
以下是以 tools
jar 模式启动 jar 的方法:
$ java -Djarmode=tools -jar my-app.jar
这将输出如下内容:
Usage: java -Djarmode=tools -jar my-app.jar Available commands: extract Extract the contents from the jar list-layers List layers from the jar that can be extracted help Help about any command
extract
命令可轻松将应用拆分为可添加到 Dockerfile
的分层。
以下是使用 jarmode
的 Dockerfile
示例。
# Perform the extraction in a separate builder container
FROM bellsoft/liberica-openjre-debian:24-cds AS builder
WORKDIR /builder
# This points to the built jar file in the target folder
# Adjust this to 'build/libs/*.jar' if you're using Gradle
ARG JAR_FILE=target/*.jar
# Copy the jar file to the working directory and rename it to application.jar
COPY ${JAR_FILE} application.jar
# Extract the jar file using an efficient layout
RUN java -Djarmode=tools -jar application.jar extract --layers --destination extracted
# This is the runtime container
FROM bellsoft/liberica-openjre-debian:24-cds
WORKDIR /application
# Copy the extracted jar contents from the builder container into the working directory in the runtime container
# Every copy step creates a new docker layer
# This allows docker to only pull the changes it really needs
COPY --from=builder /builder/extracted/dependencies/ ./
COPY --from=builder /builder/extracted/spring-boot-loader/ ./
COPY --from=builder /builder/extracted/snapshot-dependencies/ ./
COPY --from=builder /builder/extracted/application/ ./
# 启动应用 jar —— 这不是 builder 使用的 uber jar
# 此 jar 仅包含应用代码及对已提取 jar 文件的引用
# 这种布局启动高效,且对 CDS/AOT 缓存友好
ENTRYPOINT ["java", "-jar", "application.jar"]
假设上述 Dockerfile
位于当前目录,可用 docker build .
构建镜像,或如下面例子指定应用 jar 路径:
$ docker build --build-arg JAR_FILE=path/to/myapp.jar .
这是一个多阶段 Dockerfile
。
builder 阶段会提取后续需要的目录。
每个 COPY
命令都对应 jarmode 提取的分层。
当然,也可以不用 jarmode
编写 Dockerfile
。
你可以用 unzip
和 mv
等组合将内容移到正确分层,但 jarmode
简化了这一过程。
此外,jarmode
创建的布局天生支持 CDS 和 AOT 缓存。
CDS
如果你还想启用 CDS,可使用如下 Dockerfile
:
# Perform the extraction in a separate builder container
FROM bellsoft/liberica-openjre-debian:24-cds AS builder
WORKDIR /builder
# This points to the built jar file in the target folder
# Adjust this to 'build/libs/*.jar' if you're using Gradle
ARG JAR_FILE=target/*.jar
# Copy the jar file to the working directory and rename it to application.jar
COPY ${JAR_FILE} application.jar
# Extract the jar file using an efficient layout
RUN java -Djarmode=tools -jar application.jar extract --layers --destination extracted
# This is the runtime container
FROM bellsoft/liberica-openjre-debian:24-cds
WORKDIR /application
# Copy the extracted jar contents from the builder container into the working directory in the runtime container
# Every copy step creates a new docker layer
# This allows docker to only pull the changes it really needs
COPY --from=builder /builder/extracted/dependencies/ ./
COPY --from=builder /builder/extracted/spring-boot-loader/ ./
COPY --from=builder /builder/extracted/snapshot-dependencies/ ./
COPY --from=builder /builder/extracted/application/ ./
# 执行 CDS 训练运行
RUN java -XX:ArchiveClassesAtExit=application.jsa -Dspring.context.exit=onRefresh -jar application.jar
# 启动已启用 CDS 的应用 jar —— 这不是 builder 使用的 uber jar
# 此 jar 仅包含应用代码及对已提取 jar 文件的引用
# 这种布局启动高效且对 CDS 友好
ENTRYPOINT ["java", "-XX:SharedArchiveFile=application.jsa", "-jar", "application.jar"]
这与上面的 Dockerfile
基本一致。
最后一步通过训练运行创建 CDS 存档,并将 CDS 参数传递给 java -jar
。
AOT cache
如果你还想启用 AOT cache,可使用如下 Dockerfile
:
# Perform the extraction in a separate builder container
FROM bellsoft/liberica-openjre-debian:24-cds AS builder
WORKDIR /builder
# This points to the built jar file in the target folder
# Adjust this to 'build/libs/*.jar' if you're using Gradle
ARG JAR_FILE=target/*.jar
# Copy the jar file to the working directory and rename it to application.jar
COPY ${JAR_FILE} application.jar
# Extract the jar file using an efficient layout
RUN java -Djarmode=tools -jar application.jar extract --layers --destination extracted
# This is the runtime container
FROM bellsoft/liberica-openjre-debian:24-cds
WORKDIR /application
# Copy the extracted jar contents from the builder container into the working directory in the runtime container
# Every copy step creates a new docker layer
# This allows docker to only pull the changes it really needs
COPY --from=builder /builder/extracted/dependencies/ ./
COPY --from=builder /builder/extracted/spring-boot-loader/ ./
COPY --from=builder /builder/extracted/snapshot-dependencies/ ./
COPY --from=builder /builder/extracted/application/ ./
# 执行 AOT 缓存训练运行
RUN java -XX:AOTMode=record -XX:AOTConfiguration=app.aotconf -Dspring.context.exit=onRefresh -jar application.jar
RUN java -XX:AOTMode=create -XX:AOTConfiguration=app.aotconf -XX:AOTCache=app.aot -jar application.jar && rm app.aotconf
# 启动已启用 AOT 缓存的应用 jar —— 这不是 builder 使用的 uber jar
# 此 jar 仅包含应用代码及对已提取 jar 文件的引用
# 这种布局启动高效且对 AOT 缓存友好
ENTRYPOINT ["java", "-XX:AOTCache=app.aot", "-jar", "application.jar"]
这与上面的 Dockerfile
基本一致。
最后一步通过训练运行创建 AOT 缓存文件,并将 AOT 缓存参数传递给 java -jar
。