简介
在文章《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
应用了 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/p…