> Java > java지도 시간 > 본문

GraalVM 빌더를 사용하여 Spring Boot 애플리케이션에서 네이티브 이미지 빌드

WBOY
풀어 주다: 2024-08-05 20:04:50
원래의
562명이 탐색했습니다.

Build native image from Spring Boot Application with GraalVM builder

개요

이 섹션에서는 GraalVM의 네이티브 이미지 빌더를 사용하여 Spring Boot 애플리케이션에서 네이티브 이미지를 생성하는 방법과 이 네이티브 이미지를 Docker 컨테이너에서 실행하는 방법을 설명합니다.

목적

소프트웨어 아키텍처와 마이크로서비스 아키텍처 설계에서는 애플리케이션의 확장성과 성능을 고려해야 합니다. 우리 애플리케이션은 요청 수가 증가할 때마다 신속하게 확장을 시작하고 리소스를 효율적으로 활용해야 합니다.

GraalVM과 함께 AOT(Spring Boot Ahead of Time) 컴파일을 사용하여 Java 가상 스레드(JDK 21 이상에서 사용 가능)와 함께 컨테이너에서 실행 파일을 실행하는 것을 고려하고 있습니다.

  • AOT 컴파일은 런타임 적응성이 떨어지는 대신 빠른 시작 시간과 예측 가능한 성능이 중요한 시나리오에 유리합니다.
  • 컨테이너는 호스트 OS 커널을 공유하기 때문에 가상 머신(VM)에 비해 가볍고 리소스를 덜 사용합니다. 컨테이너는 VM보다 훨씬 빠르게 시작하고 중지할 수 있으므로 더 빠른 확장과 배포가 가능합니다.
  • 가상 스레드는 많은 수의 동시 작업을 처리하는 애플리케이션의 성능을 향상시킬 수 있습니다. 이는 웹 서버, 데이터베이스 및 기타 I/O 바인딩 시스템과 같은 애플리케이션에 특히 유용합니다. 가상 스레드는 기존 스레드보다 적은 리소스를 사용합니다. 메모리 사용량과 CPU 오버헤드를 최소화하는 방식으로 런타임에 의해 관리됩니다.

이 아키텍처 설계 결정에서는 이점을 얻지만 다음 구현 과제와 설계 고려 사항도 고려해야 합니다.

  • 가상 스레드: 광범위한 메모리 계산이 필요한 시나리오와 같이 비즈니스 로직이 CPU 집약적이라면 가상 스레드 사용을 피해야 합니다.
  • AOT(Ahead of Time) 컴파일: AOT 컴파일러는 리플렉션, 프록시 코딩 또는 직렬화를 제대로 처리하지 못할 수 있습니다. 또한 GraalVM은 Spring Boot 애플리케이션에서 기본 이미지를 생성하는 데 어려움을 겪고 빌드 시간이 늘어나는 비교적 새로운 기술입니다.
  • 컨테이너: 컨테이너는 수많은 이점을 제공하지만 영역 보안, 네트워크, 성능, CI/CD 등과 관련된 몇 가지 과제가 있습니다. 몇 가지 예는 다음과 같습니다.
    • 컨테이너에는 기본 이미지 또는 종속성의 취약점이 포함될 수 있습니다.
    • 컨테이너를 기존 CI/CD 파이프라인에 통합하는 것은 어려울 수 있으며 빌드, 테스트, 배포 프로세스를 변경해야 합니다.
    • Kubernetes와 같은 컨테이너 오케스트레이션 플랫폼을 관리하는 것은 복잡할 수 있으며 전문 지식이 필요할 수 있습니다.
    • 컨테이너를 효율적으로 확장 및 축소하여 리소스를 과도하게 프로비저닝하거나 부족하게 프로비저닝하지 않고 다양한 로드를 처리합니다.

Spring Boot 애플리케이션
이 사용 사례를 테스트하기 위해 "/hello"에 REST 끝점을 노출하는 Spring Boot 애플리케이션을 구축하고 있습니다. 저는 다음 구성, 라이브러리 및 도구를 사용하고 있습니다.

  • REST가 포함된 Spring Boot 3.2.8
  • 스프링 부트 AOT 컴파일
  • 스프링 부트 GraalVM 네이티브 이미지
  • Maven 3.9.8 빌드 도구
  • 자바 22

POM XML 파일에 다음 구성을 추가해야 합니다.

Spring Boot 속성 구성

<properties>
    <java.version>22</java.version>
    <spring-native.version>0.12.1</spring-native.version>
</properties>
로그인 후 복사

Spring Boot AOT 플러그인 구성

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
       <execution>
          <id>process-aot</id>
          <goals>
             <goal>process-aot</goal>
          </goals>
       </execution>
    </executions>
</plugin>
로그인 후 복사

GraalVM 플러그인 구성

<plugin>
    <groupId>org.graalvm.buildtools</groupId>
    <artifactId>native-maven-plugin</artifactId>
    <configuration>
       <imageName>app-native-binary</imageName>
       <metadataRepository>
          <enabled>true</enabled>
       </metadataRepository>
       <buildArgs>
          <buildArg>--static --libc=musl</buildArg>
          <buildArg>-H:+ReportExceptionStackTraces</buildArg>
       </buildArgs>
       <mainClass>com.developerhelperhub.tutorial.springboot.tutorial.TutorialStartupPerformanceApplication</mainClass>
    </configuration>
    <executions>
       <execution>
          <id>add-reachability-metadata</id>
          <goals>
             <goal>add-reachability-metadata</goal>
          </goals>
       </execution>
    </executions>
</plugin>
로그인 후 복사
  • "mainClass": 스프링 부트 애플리케이션의 메일 클래스 구성
  • "imageName": 네이티브 이미지 이름 구성
  • "buildArgs": —libc=”msul” 구성, 이 이미지를 Alpine Linux 상자에서 실행할 것이기 때문에 "libc musl" 호환 라이브러리를 사용하여 네이티브 이미지를 빌드하도록 GraalVM을 구성하고 있습니다. Musl은 다른 표준 라이브러리에 비해 더 작고 메모리를 적게 사용하도록 설계되어 리소스가 제한된 환경에 적합합니다.

바이너리 빌드 및 Docker 이미지 생성

컨테이너 내에서 네이티브 이미지가 실행될 특정 OS 호스트 및 CPU 아키텍처에 대한 네이티브 이미지를 빌드해야 합니다.

우리는 컨테이너에서 애플리케이션을 실행하기 위해 작은 크기, 단순성 및 보안을 위해 Alpine Linux를 사용하고 있습니다. 이를 달성하려면 애플리케이션 구축에 적합한 GraalVM 구성을 사용해야 합니다. Alpine의 시스템 요구 사항은 운영 체제와 CPU 아키텍처입니다.

  • "아키텍처": "amd64"
  • "Os": "리눅스"
  • C 공용 라이브러리: “libc musl”

다음 명령을 사용하여 "amd64/alpine" 이미지를 검사할 수 있습니다

docker pull amd64/alpine # pull the image

docker image inspect amd64/alpine # inspect the image
로그인 후 복사

We can use docker container to build the native image instead of setup the GraalVM and Java related configuration in our locally. I am using “ghcr.io/graalvm/native-image-community:22-muslib” docker image to build the native.

Following command we can use to inspect the “ghcr.io/graalvm/native-image-community:22-muslib” image

docker pull ghcr.io/graalvm/native-image-community:22-muslib # pull the image

docker image inspect ghcr.io/graalvm/native-image-community:22-muslib # inspect the image
로그인 후 복사

I am creating a build image to test and debug the container, ensuring that all configurations and services are installed correctly. This approach will help us quickly identify and resolve any issues.

Following steps are added in the docker file, the file name “DockerfileBuild”

FROM ghcr.io/graalvm/native-image-community:22-muslib as build

# Install necessary tools
RUN microdnf install wget 
RUN microdnf install xz

# Install maven for build the spring boot application
RUN wget https://dlcdn.apache.org/maven/maven-3/3.9.8/binaries/apache-maven-3.9.8-bin.tar.gz
RUN tar xvf apache-maven-3.9.8-bin.tar.gz

# Set up the environment variables needed to run the Maven command.
ENV M2_HOME=/app/apache-maven-3.9.8
ENV M2=$M2_HOME/bin
ENV PATH=$M2:$PATH

# Install UPX (Ultimate Packer for eXecutables) to compress the executable binary and reduce its size.
RUN wget https://github.com/upx/upx/releases/download/v4.2.4/upx-4.2.4-amd64_linux.tar.xz
RUN tar xvf upx-4.2.4-amd64_linux.tar.xz

# Set up the environment variables required to run the UPX command.
ENV UPX_HOME=/app/upx-4.2.4-amd64_linux
ENV PATH=$UPX_HOME:$PATH

#Copy the spring boot source code into container
RUN mkdir -p /app/spring-boot-rest-api-app
COPY spring-boot-rest-api-app /app/spring-boot-rest-api-app

#Compile the native image
RUN cd /app/spring-boot-rest-api-app && mvn -Pnative native:compile

#Compressed binary file
RUN upx -7 -k /app/spring-boot-rest-api-app/target/app-native-binary
WORKDIR /app
ENTRYPOINT ["/bin/bash"]
로그인 후 복사

I am using the UPX compression tool in the build process to reduce the image size, UPX will typically reduce the file size of programs and DLLs by around 50%-70%, thus reducing disk space, network load times, download times and other distribution and storage costs.

Use the following command to build the Docker image.

docker build --no-cache -f DockerfileBuild -t alpine-graalvm-build .
로그인 후 복사

After the build is complete, the image size will be 1.85 GB.

REPOSITORY                               TAG         IMAGE ID       CREATED          SIZE
alpine-graalvm-build                     latest      81d23bc1bc99   36 seconds ago   1.85GB
로그인 후 복사

We can verify the configuration and installation within the container before creating a smaller container inside the Alpine Linux box. The following command will allow us to enter the container:

docker run --rm -it --entrypoint /bin/bash alpine-graalvm-build

java --version #verify the java version
mvn --version #verify the maven version
upx --version #verify the upx version

ls /app/spring-boot-rest-api-app/target/app-native-binary #verify the binary available

/app/spring-boot-rest-api-app/target/app-native-binary #run the executable
로그인 후 복사

We know that this native image includes all the dependencies necessary to run the binary standalone, without requiring any build-related tools such as GraalVM, Maven, UPX, or source code. We can use a Docker multi-stage build approach to copy the build file into our application image. By using multiple stages, you can separate the build environment from the runtime environment. This means only the necessary artifacts are included in the final image, significantly reducing its size.

Following steps are added in the docker file, the file name “DockerfileBuildAndCreateAlpineContainer”

FROM ghcr.io/graalvm/native-image-community:22-muslib as build

# Install necessary tools
RUN microdnf install wget 
RUN microdnf install xz

# Install maven for build the spring boot application
RUN wget https://dlcdn.apache.org/maven/maven-3/3.9.8/binaries/apache-maven-3.9.8-bin.tar.gz
RUN tar xvf apache-maven-3.9.8-bin.tar.gz

# Set up the environment variables needed to run the Maven command.
ENV M2_HOME=/app/apache-maven-3.9.8
ENV M2=$M2_HOME/bin
ENV PATH=$M2:$PATH

# Install UPX (Ultimate Packer for eXecutables) to compress the executable binary and reduce its size.
RUN wget https://github.com/upx/upx/releases/download/v4.2.4/upx-4.2.4-amd64_linux.tar.xz
RUN tar xvf upx-4.2.4-amd64_linux.tar.xz

# Set up the environment variables required to run the UPX command.
ENV UPX_HOME=/app/upx-4.2.4-amd64_linux
ENV PATH=$UPX_HOME:$PATH

#Copy the spring boot source code into container
RUN mkdir -p /app/spring-boot-rest-api-app
COPY spring-boot-rest-api-app /app/spring-boot-rest-api-app

#Compile the native image
RUN cd /app/spring-boot-rest-api-app && mvn -Pnative native:compile

#Compressed binary file
RUN upx -7 -k /app/spring-boot-rest-api-app/target/app-native-binary
WORKDIR /app

#Second stage: Create the runtime image
FROM amd64/alpine

#Set the working directory
WORKDIR /app

#Copy the built application from the first stage
COPY --from=build /app/spring-boot-rest-api-app/target/app-native-binary .

#Expose port which our spring boot application is running
EXPOSE 8080 

#Command to run the application
ENTRYPOINT ["/app/app-native-binary"]
로그인 후 복사

Use the following command to build the Docker image.

docker build -f DockerfileBuildAndCreateAlpineContainer -t alpine-graalvm .
로그인 후 복사

After the build is complete, the image size of container will be 32.8MB.

REPOSITORY                               TAG         IMAGE ID       CREATED          SIZE
alpine-graalvm                           latest      79676c696920   11 seconds ago      32.8MB
로그인 후 복사

We can verify the container.

docker run --rm -it --entrypoint sh alpine-graalvm

ls /app #verify the binary available

/app/app-native-binary #run the executable
로그인 후 복사

The application startup time is just 0.074 seconds, whereas a typical Spring Boot application running on the JVM has a startup time of approximately 1.665 seconds.

Started TutorialStartupPerformanceApplication in 0.074 seconds (process running for 0.075)
로그인 후 복사

Following command can be use to run the docker container for running the application

docker run -d --name test-app -p 8080:8080 alpine-graalvm #run the container

curl http://localhost:8080/hello # checking the endpoints
로그인 후 복사

Spring boot and GraalVM references

  • Spring Boot Introduction GraalVM Native Images
  • GraalVM documentation build Spring Boot Native Executable
  • GraalVM Maven Plugin Documentation
  • Sample Spring Boot Application Docker Image Setup with GraalVM
  • Sample Native Images with Spring Boot and GraalVM
  • Spring Boot 3.2.8 GraalVM Native Images Documentation
  • Spring Boot GraalVM UPX Tutorial Video
  • Spring Boot Alpine Linux Docker Native Image Example ## Docker and GraalVM References
  • GraalVM Containers Images
  • Docker Environment Variables
  • Maven Download
  • UPX Documentation
  • UPX Releases
  • Docker Stop Container

Source Code

  • Spring Boot Github Repo
  • Kubernetes Related Repo

위 내용은 GraalVM 빌더를 사용하여 Spring Boot 애플리케이션에서 네이티브 이미지 빌드의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!