Dockerfile
虽然可以通过在 Dockerfile
中编写几行代码将 Spring Boot 的 uber jar 转换为 Docker 镜像,但使用分层功能将生成一个经过优化的镜像。当你创建一个包含分层索引文件的 jar 时,spring-boot-jarmode-tools
jar 将被添加为你的 jar 的依赖项。通过将这个 jar 放在类路径上,你可以在特殊模式下启动你的应用程序,这使得引导代码能够运行与你的应用程序完全不同的内容,例如提取分层的操作。
tools
模式不能与包含启动脚本的完全可执行的 Spring Boot 归档文件一起使用。在构建打算与 extract
工具模式命令一起使用的 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:17-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:17-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 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
。你可以使用 unzip
和 mv
的组合将文件移动到正确的层级,但 jarmode
简化了这一过程。此外,jarmode
创建的布局默认就是 CDS 友好的。
CDS
如果你想额外启用 CDS,你可以使用这个 Dockerfile
:
# Perform the extraction in a separate builder container
FROM bellsoft/liberica-openjre-debian:17-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:17-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
。