编译native镜像的镜像优化方案

2024/08/27 GraalVM 共 2862 字,约 9 分钟
Bob.Zhu

为了避免因为编译平台不一致导致的部署文件不一样,可以使用Docker进行编译,以保证编译环境的一致性, 参考:编译native镜像的两种方法:本地 & docker

但是,Docker编译的时候,会有一些缺点,比如下载依赖文件、编译时间过长等问题。为了解决这些问题,可以使用一些优化方案。

方案1:原始编译部署方案

Dockerfile.native

FROM bellsoft/liberica-native-image-kit-container:jdk-22-nik-24.0.2-glibc as builder
WORKDIR /home/build
COPY . /home/build/
RUN ./mvnw -Pnative clean -DskipTests native:compile

FROM bellsoft/alpaquita-linux-base:stream-glibc-240821
WORKDIR /home/myapp
COPY --from=builder /home/build/target/flutter-flex-backend .
EXPOSE 8080
CMD ["/bin/sh", "-c", "/home/myapp/flutter-flex-backend"]
  • 缺点:需要下载maven依赖,耗时较长

方案2:拆分编译部署

# bellsoft的NIK镜像
docker pull bellsoft/liberica-native-image-kit-container:jdk-22-nik-24.0.2-glibc
# 映射本地文件和maven仓库进行编译
docker run -it --rm --name temp-container \
  -v $PWD:/home/build \
  -v $HOME/.m2:/root/.m2 \
  bellsoft/liberica-native-image-kit-container:jdk-22-nik-24.0.2-glibc \
  /bin/sh -c "cd /home/build && ./mvnw -Pnative clean -DskipTests native:compile"
# 运行测试
docker run -it --rm --name temp-container \
  -v $PWD/target/flutter-flex-backend:/home/myapp/flutter-flex-backend \
  -p 8080:8080 \
  bellsoft/alpaquita-linux-base:stream-glibc-240821 \
  /bin/sh -c "cd /home/myapp && ./flutter-flex-backend"
  • 优点:充分利用本地maven仓库,减少下载时间
  • 缺点:比较繁琐,但是可以配置快捷指令

方案3:映射本地maven仓库

在docker run 的时候可以直接映射宿主机文件夹,但是在build期间不能映射,只能执行COPY操作,所以需要在Dockerfile中COPY maven仓库到镜像中。

  • Dockerfile将maven仓库拷贝到镜像中的配置:COPY .m2 /root/.m2
  • 在$HOME目录下,执行 build 操作:因为build期间的COPY指令,只能拷贝当前目录或者子目录下的文件

Dockerfile.native

FROM bellsoft/liberica-native-image-kit-container:jdk-22-nik-24.0.2-glibc as builder
COPY .m2 /root/.m2
WORKDIR /home/build
COPY . /home/build/
RUN ./mvnw -Pnative clean -DskipTests native:compile

FROM bellsoft/liberica-runtime-container:jdk-21.0.4-crac-cds-slim-glibc
WORKDIR /home/myapp
COPY --from=builder /home/build/target/flutter-flex-backend.jar .
EXPOSE 8080
CMD ["java", "-jar", "/home/myapp/flutter-flex-backend.jar"]
  • 缺点:需要切换操作目录到$HOME,否则会拷贝不到maven仓库,且拷贝的无用依赖文件较多,会增加镜像大小

方案4:构建包含缓存的编译镜像

构建镜像描述文件:

Dockerfile-build

FROM bellsoft/liberica-native-image-kit-container:jdk-22-nik-24.0.2-glibc as builder
WORKDIR /home/build
COPY . /home/build/
RUN ./mvnw -Pnative clean -DskipTests package
RUN rm -rf /home/build/

需要在项目根目录下执行,以便拷贝项目文件,编译镜像名称mytool-group-develop:jdk-22-nik-24.0.2-glibc-with-m2

docker build --platform=linux/amd64 -f Dockerfile.build -t mytool-group-develop:jdk-22-nik-24.0.2-glibc-with-m2 .

使用范例:

Dockerfile.native

FROM mytool-group-develop:jdk-22-nik-24.0.2-glibc-with-m2 as builder
WORKDIR /home/build
COPY . /home/build/
RUN ./mvnw -Pnative clean -DskipTests native:compile

FROM bellsoft/alpaquita-linux-base:stream-glibc-240821
WORKDIR /home/myapp
COPY --from=builder /home/build/target/flutter-flex-backend .
EXPOSE 8080
CMD ["/bin/sh", "-c", "/home/myapp/flutter-flex-backend"]
  • 优点:构建镜像时,可以利用缓存,减少编译时间
  • 缺点:当maven仓库有变动时,需要重新构建编译镜像

总结

  • 原始编译部署方案:分发项目的时候使用此方案,使用的是公共镜像,保证了编译环境的一致性
  • ⚠️ 拆分编译部署:本地开发的时候可以使用此方案,充分使用本地maven缓存资源
  • 映射本地maven仓库:不推荐使用,构建的时候必须进入$HOME目录,不方便使用
  • 构建包含缓存的编译镜像:推荐使用,只需要在maven依赖变更的时候重新构建一次就可以使用缓存

参考资料

文档信息

Search

    Table of Contents