使用本机构建 graal native 程序我们需要对环境进行配置,例如包括 graalvm、maven、native-image,如果我们把这些内容放在 docker 构建中执行,便不会占用宿主机的空间,也不会影响到宿主机的配置。最终形成的 docker 镜像文件也可以直接启动使用。

将以下内容存储为 Dockerfile 然后放置在 maven 项目的根目录下(同 pom.xml 文件放一起)后,再执行 docker 构建命令:

docker build spring-native-demo:.0.0.1 .

如下提供两个 Dockerfile 示例,供参考,公司项目推荐使用离线模式的示例2。

Dockerfile 示例1

# Simple Dockerfile adding Maven and GraalVM Native Image compiler to the standard
# 镜像版本号来自 graalvm 官网 https://github.com/graalvm/container/pkgs/container/graalvm-ce
FROM ghcr.io/graalvm/graalvm-ce:ol8-java17-22.2.0
 
ADD . /build
WORKDIR /build

RUN \
    # For SDKMAN to work we need unzip & zip
    # yum install -y unzip zip (graalvm/graalvm-c 默认没有yum所以改用rpm安装)
    rpm -ivh https://yum.oracle.com/repo/OracleLinux/OL8/baseos/latest/x86_64/getPackage/unzip-6.0-46.el8.x86_64.rpm && \
    rpm -ivh https://yum.oracle.com/repo/OracleLinux/OL8/baseos/latest/x86_64/getPackage/zip-3.0-23.el8.x86_64.rpm && \
    # Install SDKMAN
    curl -s "https://get.sdkman.io" | bash; \
    source "$HOME/.sdkman/bin/sdkman-init.sh"; \
    sdk install maven; \
    # Install GraalVM Native Image
    gu install native-image;
 
RUN source "$HOME/.sdkman/bin/sdkman-init.sh" && mvn --version && native-image --version

RUN source "$HOME/.sdkman/bin/sdkman-init.sh" && mvn -Pnative clean package -DskipTests
 
# We use a Docker multi-stage build here in order to only take the compiled native Spring Boot App from the first build container
FROM oraclelinux:7-slim

MAINTAINER SHANHY
 
# Add Spring Boot Native app spring-boot-graal to Container
COPY --from=0 "/build/target/spring-native-demo" spring-native-demo

ENV PORT=8081

# Fire up our Spring Boot Native app by default
CMD [ "sh", "-c", "./spring-native-demo -Dserver.port=$PORT" ]

其中 rpm 包的下载地址源自 Oracle Linux 官网

# Oracle Linux 7 
http://yum.oracle.com/repo/OracleLinux/OL7/latest/x86_64/index.html
# 对应索引页
http://yum.oracle.com/oracle-linux-7.html

# Oracle linux 8 
http://yum.oracle.com/repo/OracleLinux/OL8/baseos/latest/x86_64/index.html
# 对应索引页
http://yum.oracle.com/oracle-linux-8.html

脚本中的主要步骤解释如下:
1、使用 oracle/graalvm-ce:20.1.0-java11 作为基础镜像(根据需求更换你需要的版本)
2、在基础镜像中安装 sdkman、基于sdkman安装maven、安装 native-image
3、进行maven构建打包(如果你maven连接私服则需要将maven配置文件加入进来)
4、进行第二阶段镜像构建,基础镜像为 oraclelinux:7-slim(根据需求更换你需要的镜像)
5、将第一阶段镜像的构建结果 COPY 到当前二阶段镜像中,命名为 spring-boot-graal
6、最终运行构建后的程序,启动服务,这里依然可以像运行 jar 一样通过 -D 传递参数
整个构建结束后一阶段镜像的所有内容不会保留,只会剩下仅包含应用程序的二阶段镜像。
建议将一阶段除最后一步maven构建以上的所有步骤做成一个本地镜像,这样省去每次联网下载安装maven和native-image的过程,提高效率。

关于文中提到的 sdkman:它是一个管理多个sdk版本的工具,支持 Java、Scala、Flink、Spark、Hadoop、Maven、Sbt 等,我们使用它来便捷的安装各种 sdk。

参考文章:https://blog.codecentric.de/en/2020/06/spring-boot-graalvm-native-image-maven-plugin/


Dockerfile 示例2(推荐)

# Simple Dockerfile adding Maven and GraalVM Native Image compiler to the standard
# 镜像版本号来自 graalvm 官网 https://github.com/graalvm/container/pkgs/container/graalvm-ce
FROM ghcr.io/graalvm/graalvm-ce:ol8-java17-22.2.0

ADD https://192.168.1.111/files/apache-maven-3.8.6.tar /tools/
ADD https://192.168.1.111/files/native-image-installable-svm-java17-linux-amd64-22.2.0.jar /tools/
COPY . /build

WORKDIR /tools
RUN set -x && \
    tar -xvf apache-maven-*.tar && \
    rm -rf apache-maven-*.tar && \
    mv apache-maven-* maven && \
    mv native-image-installable-*.jar native-image-installable.jar && \
    export MAVEN_HOME=/tools/maven && \
    export PATH=$PATH:$MAVEN_HOME/bin && \
    gu -L install native-image-installable.jar && \
    mvn --version && \
    native-image --version && \
    cd /build && \
    mvn -Pnative clean package -DskipTests

# We use a Docker multi-stage build here in order to only take the compiled native Spring Boot App from the first build container
FROM oraclelinux:7-slim
 
MAINTAINER Shanhy
 
# Add Spring Boot Native app spring-boot-graal to Container
COPY --from=0 "/build/target/spring-native-demo" spring-native-demo

ENV PORT=8081

# Fire up our Spring Boot Native app by default
CMD [ "sh", "-c", "./spring-native-demo -Dserver.port=$PORT" ]

示例2相比示例1更清晰,更适合离线服务器环境,有几个要点说明如下:
1、apache-maven-3.8.6.tar 是自己本地修改好配置文件后使用 7z 压缩的,主要包含maven私服的配置
2、ADD 命令从本地环境下载
3、RUN 中的命令纯手工配置环境,最后进行maven构建项目

使用示例2Dockerfile 的 spring-native-demo 源代码地址为:https://github.com/xzxiaoshan/spring-native-demo


(END)

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐