跳到主要内容
版本:3.5.10

Dockerfiles

QWen Max 中英对照 Dockerfiles

虽然只需在 Dockerfile 中写几行代码,就可以将 Spring Boot 的 uber jar 转换为 Docker 镜像,但使用 分层功能 将生成一个优化后的镜像。当你创建一个包含分层索引文件(layers index file)的 jar 时,spring-boot-jarmode-tools jar 会被作为依赖项添加到你的 jar 中。当该 jar 位于 classpath 上时,你可以以一种特殊模式启动应用程序,使得引导代码可以运行与你的应用程序完全不同的内容,例如用于提取分层的工具。

警告

tools 模式不能与包含启动脚本的完全可执行的 Spring Boot 归档文件一起使用。在构建打算用于 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 中。以下是一个使用 jarmodeDockerfile 示例。

# 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/ ./
# Start the application jar - this is not the uber jar used by the builder
# This jar only contains application code and references to the extracted jar files
# This layout is efficient to start up and CDS/AOT cache friendly
ENTRYPOINT ["java", "-jar", "application.jar"]

假设上述 Dockerfile 位于当前目录中,你可以使用 docker build . 来构建 Docker 镜像,或者也可以选择指定应用程序 jar 文件的路径,如下例所示:

$ docker build --build-arg JAR_FILE=path/to/myapp.jar .

这是一个多阶段的 Dockerfile。构建器阶段会提取后续所需的目录。每个 COPY 命令都与 jarmode 提取的层相关。

当然,Dockerfile 也可以在不使用 jarmode 的情况下编写。你可以通过结合使用 unzipmv 命令将内容移动到正确的层,但 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/ ./
# Execute the CDS training run
RUN java -XX:ArchiveClassesAtExit=application.jsa -Dspring.context.exit=onRefresh -jar application.jar
# Start the application jar with CDS enabled - this is not the uber jar used by the builder
# This jar only contains application code and references to the extracted jar files
# This layout is efficient to start up and CDS friendly
ENTRYPOINT ["java", "-XX:SharedArchiveFile=application.jsa", "-jar", "application.jar"]

这与上面的 Dockerfile 基本相同。在最后几步中,它通过一次训练运行创建了 CDS 归档,并将 CDS 参数传递给 java -jar

AOT 缓存

如果你想额外启用 AOT 缓存,可以使用以下 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/ ./
# Execute the AOT cache training run
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
# Start the application jar with AOT cache enabled - this is not the uber jar used by the builder
# This jar only contains application code and references to the extracted jar files
# This layout is efficient to start up and AOT cache friendly
ENTRYPOINT ["java", "-XX:AOTCache=app.aot", "-jar", "application.jar"]

这与上面的 Dockerfile 基本相同。在最后几步中,它通过一次训练运行创建了 AOT 缓存文件,并将 AOT 缓存参数传递给 java -jar