3

Spring Native打包本地镜像,无需通过Graal的maven插件buildtools

 1 year ago
source link: https://www.pkslow.com/archives/spring-boot-native-without-buildtools
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

在文章《GraalVM和Spring Native尝鲜,一步步让Springboot启动飞起来,66ms完成启动》中,我们介绍了如何使用Spring Native和buildtools插件,打包出本地镜像,也打包成Docker镜像。本文探索一下,如果不通过这个插件来生成镜像。这样我们可以控制更多、了解更多。

创建Spring Boot项目

创建Spring Boot项目,引入Spring Native,我们主要使用的是Spring Native提供的AOT功能。如下:

<dependencies>
  <dependency>
    <groupId>org.springframework.experimental</groupId>
    <artifactId>spring-native</artifactId>
    <version>${spring-native.version}</version>
  </dependency>

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
</dependencies>

<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.experimental</groupId>
      <artifactId>spring-aot-maven-plugin</artifactId>
      <version>${spring-native.version}</version>
      <executions>
        <execution>
          <id>test-generate</id>
          <goals>
            <goal>test-generate</goal>
          </goals>
        </execution>
        <execution>
          <id>generate</id>
          <goals>
            <goal>generate</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

Build image的时候,我们需要引用依赖库,所以加上下面的插件:

<plugin>
  <artifactId>maven-dependency-plugin</artifactId>
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>copy-dependencies</goal>
      </goals>
      <configuration>
        <outputDirectory>${project.build.directory}/lib</outputDirectory>
      </configuration>
    </execution>
  </executions>
</plugin>

接着先编译出Java class,命令如下:

$ mvn clean package

打包本地镜像

前面的命令打包完,在target目录下会有一个lib目录,我们需要用上。通过native-image命令来生成镜像,如下:

$ native-image -cp ./target/classes/:target/lib/* com.pkslow.springboot.SpringbootGraalVMNativeMain Pkslow.SpringbootGraalVMNativeMain

这样就会生成一个可执行文件:Pkslow.SpringbootGraalVMNativeMain

执行如下:

$ ./Pkslow.SpringbootGraalVMNativeMain

spring-boot-native-without-buildtools.native-startup.png

使用了93ms来启动,还是很快的。

访问服务是正常的:

$ curl -i http://localhost:8080/hi-graalvm
HTTP/1.1 200 
Content-Type: text/plain;charset=UTF-8
Content-Length: 67
Date: Wed, 02 Nov 2022 15:08:44 GMT

This message is from Spring Boot built/run by GraalVM/Spring Native

创建Docker镜像

先拉取基础镜像:

$ docker pull springci/graalvm-ce:java11-0.12.x

进入容器看一下里面的状况:

$ docker run -it --rm --entrypoint bash springci/graalvm-ce:java11-0.12.x
root@d9b54bdce70a:/# pwd
/
root@d9b54bdce70a:/# java --version
openjdk 11.0.15 2022-04-19
OpenJDK Runtime Environment GraalVM 22.1.1.0-dev (build 11.0.15+10-jvmci-22.1-b06)
OpenJDK 64-Bit Server VM GraalVM 22.1.1.0-dev (build 11.0.15+10-jvmci-22.1-b06, mixed mode, sharing)
root@d9b54bdce70a:/# which java
/opt/java/bin/java
root@d9b54bdce70a:/# which native-image
/opt/java/bin/native-image

准备一下Dockerfile如下:

FROM springci/graalvm-ce:java11-0.12.x
VOLUME /tmp

ARG PORT=8080
ARG TIME_ZONE=Asia/Shanghai

ENV TZ=${TIME_ZONE}
EXPOSE ${PORT}
RUN pwd

RUN mkdir /pkslow-application
WORKDIR /pkslow-application/
RUN cd /pkslow-application
COPY target/classes/ /pkslow-application/classes/
COPY target/lib/ /pkslow-application/lib/

RUN native-image -cp /pkslow-application/classes/:/pkslow-application/lib/* \
    com.pkslow.springboot.SpringbootGraalVMNativeMain \
    Pkslow.SpringbootGraalVMNativeMain


ENTRYPOINT ["/pkslow-application/Pkslow.SpringbootGraalVMNativeMain"]

打包Docker镜像:

$ docker build . -t pkslow/spring-boot-native-without-buildtools:1.0-SNAPSHOT -f src/main/dker/Dockerfile

完成后通过下面命令启动,57ms完成启动:

$ docker run -it -p 8080:8080 --rm pkslow/spring-boot-native-without-buildtools:0-SNAPSHOT
2022-11-02 23:48:40.918  INFO 1 --- [           main] o.s.nativex.NativeListener               : AOT mode enabled

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.2)

2022-11-02 23:48:40.920  INFO 1 --- [           main] c.p.s.SpringbootGraalVMNativeMain        : Starting SpringbootGraalVMNativeMain using Java 11.0.15 on 12528bd45fd7 with PID 1 (/pkslow-application/Pkslow.SpringbootGraalVMNativeMain started by root in /pkslow-application)
2022-11-02 23:48:40.920  INFO 1 --- [           main] c.p.s.SpringbootGraalVMNativeMain        : No active profile set, falling back to default profiles: default
2022-11-02 23:48:40.934  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2022-11-02 23:48:40.935  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-11-02 23:48:40.935  INFO 1 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.56]
2022-11-02 23:48:40.940  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-11-02 23:48:40.940  INFO 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 19 ms
2022-11-02 23:48:40.963  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-11-02 23:48:40.964  INFO 1 --- [           main] c.p.s.SpringbootGraalVMNativeMain        : Started SpringbootGraalVMNativeMain in 0.057 seconds (JVM running for 0.061)
2022-11-02 23:48:57.098  INFO 1 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-11-02 23:48:57.098  INFO 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2022-11-02 23:48:57.098  INFO 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 0 ms

测试正常启动:

$ curl -i http://127.0.0.1:8080/hi-graalvm
HTTP/1.1 200 
Content-Type: text/plain;charset=UTF-8
Content-Length: 67
Date: Wed, 02 Nov 2022 15:49:05 GMT

This message is from Spring Boot built/run by GraalVM/Spring Native

为了集成打包镜像到CI/CD中,在pom添加以下插件:

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>exec-maven-plugin</artifactId>
  <version>3.0.0</version>
  <executions>
    <execution>
      <phase>install</phase>
      <goals>
        <goal>exec</goal>
      </goals>
      <configuration>
        <skip>${docker.skip}</skip>
        <executable>docker</executable>
        <arguments>
          <argument>build</argument>
          <argument>.</argument>
          <argument>-t</argument>
          <argument>pkslow/${project.artifactId}:${project.version}</argument>
          <argument>-f</argument>
          <argument>src/main/docker/Dockerfile</argument>
        </arguments>
      </configuration>
    </execution>
  </executions>
</plugin>

通过以下命令即可生成Docker镜像:

$ mvn clean install -Ddocker.skip=false

代码请看GitHub: https://github.com/LarryDpk/pkslow-samples


References:

How to Deploy Java Application with Docker and GraalVM

Docker image


Code for all: GitHub

欢迎关注微信公众号<南瓜慢说>,将持续为你更新...

file

Recommendations:
Cloud Native
Terraform
Container: Docker/Kubernetes
Spring Boot / Spring Cloud
Https
如何制定切实可行的计划并好好执行


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK