SpringBoot Docker镜像构建方法以及Spring Boot Native构建方法
spring-boot 容器化构建
代码链接:spring-boot-docker: springboot构建docker镜像方法 (gitee.com)
环境参数
- 操作系统:WSL 2: Ubuntu 22.04.4 LTS jammy
- graal版本: Oracle GraalVM 21.0.3+7.1 (build 21.0.3+7-LTS-jvmci-23.1-b37)
- docker版本:Docker version 26.1.1, build 4cf5afa
docker镜像构建的三种方式
- spring-boot-maven-plugin
- jib-maven-plugin
- docker-maven-plugin
spring-boot-maven-plugin
重要配置
pom插件配置如下:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.2.6</version>
<configuration>
<image>
<name>${project.artifactId}:latest</name>
<createdDate>${maven.build.timestamp}</createdDate>
<!-- <builder>
dashaun/builder-arm:20240403
</builder> -->
</image>
</configuration>
</plugin>
</plugins>
</build>
优缺点
优点:几乎不用配置,全部由插件完成,只需要指定构建参数即可。然后执行命令 ./mvnw clean spring-boot:build-image
,直到构建完成。详细可以参考官方文档Packaging OCI Images :: Spring Boot。可以查看该镜像的结构,学习该结构,用于优化自己的构建。
缺点:依赖网络环境,需要连接github。因为配置文件可以指定builder,理论上可以基于默认的builder(paketobuildpakcs)来制作buidler解决网络依赖问题。但是专门为该插件定制镜像,复杂程度比直接用Dockerfile高多了,插件自身的可配置性也不够,还不如直接通过Dockerfile来构建。
jib-maven-plugin
重要配置
<build>
<plugins>
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>3.4.2</version>
<configuration>
<from>
<image>eclipse-temurin:21-jre-alpine</image>
</from>
<to>
<image>${project.artifactId}:latest</image>
</to>
<container>
<mainClass>com.alex.springbootbuilddocker.SpringBootBuildDockerApplication</mainClass>
<creationTime>USE_CURRENT_TIMESTAMP</creationTime>
</container>
</configuration>
<!--绑定dockerBuild生命周期到package阶段,即执行./mvnw package后,会自动构建镜像-->
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>dockerBuild</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
这里只配置了基础镜像、构建名称和构建时间。其余配置可以参考jib/jib-maven-plugin at master · GoogleContainerTools/jib (github.com)。该插件还可以配置registry mirrors,配置文件的位置在${HOME}/.config/google-cloud-tools-java/jib
下,不操作系统参考配置文档。
执行./mvnw clean package
即可完成构建,然后通过docker-compose启动容器。
优缺点
优点:该插件为java项目通用插件、配置简单、可配置性较强,不依赖本地docker环境(goal改为build),且构建方式也为分层构建,可以构建tar包,还可以构建后推送到远程镜像仓库(goal改为build),且不需要spring-boot-maven-plugin插件 缺点:完全用插件配置,有一定学习成本。虽然插件本身的可配置性很强,但是还是不如Dockerfile灵活
docker-maven-plugin
重要配置
pom插件配置如下:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.2.6</version>
<configuration>
<mainClass>
com.alex.springbootbuilddocker.SpringBootBuildDockerApplication
</mainClass>
<!-- <platforms>
<platform>
<architecture>arm64</architecture>
<os>linux</os>
</platform>
</platforms> -->
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>bash</executable>
<arguments>
<argument>-c</argument>
<argument>
<![CDATA[
mkdir target/extracted && \
java -Djarmode=layertools -jar target/*.jar extract --destination target/extracted
]]>
</argument>
</arguments>
</configuration>
</plugin>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.44.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<images>
<image>
<name>${project.artifactId}:latest</name>
<build>
<dockerFile>${project.basedir}/Dockerfile</dockerFile>
<contextDir>${project.basedir}</contextDir>
</build>
</image>
</images>
</configuration>
</plugin>
</plugins>
</build>
Dockerfile配置如下:
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
ARG EXTRACTED=target/extracted
COPY ${EXTRACTED}/dependencies/ ./
COPY ${EXTRACTED}/snapshot-dependencies/ ./
COPY ${EXTRACTED}/spring-boot-loader/ ./
COPY ${EXTRACTED}/application/ ./
ENV TZ="Asia/Shanghai"
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
ENTRYPOINT ["sh","-c","java org.springframework.boot.loader.launch.JarLauncher"]
该配置主要分为以下三点:
- spring-boot-maven-plugin,用于构建jar包,2.3后分层特性是默认开启的。参考官方文档:spring-boot-docker,Maven Plugin :: Spring Boot
- exec-maven-plugin,用来执行命令或脚本,用于将打好的jar包,拆成四个分层的文件夹
- docker-maven-plugin,用来构建镜像,该插件可以统一镜像名、镜像版本与pom文件一致
上面的配置同下面的脚本功能一致,脚本的优点是简单易懂,缺点是硬编码较多
./mvnw clean package -DskipTests
mkdir target/extracted
java -Djarmode=layertools -jar target/*.jar extract --destination target/extracted
docker build . -t spring-boot-build-docker:latest
优缺点
该方式的优点是各步骤相互独立,且每一步都是简单容易理解的、扩展灵活,同时不依赖网络环境。
缺点是每一步都需要理解并自己配置。
该方式多用于实际生产中。
spring boot native 镜像构建
环境参数
- 操作系统:WSL 2: Ubuntu 22.04.4 LTS jammy
- graal版本: Oracle GraalVM 21.0.3+7.1 (build 21.0.3+7-LTS-jvmci-23.1-b37)
- docker版本:Docker version 26.1.1, build 4cf5afa
重要配置
<build>
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<name>${project.artifactId}-native:latest</name>
<createdDate>${maven.build.timestamp}</createdDate>
<!-- <builder>
dashaun/builder-arm:20240403
</builder> -->
</image>
</configuration>
</plugin>
</plugins>
</build>
构建本地可执行文件
./mvnw clean native:compile -Pnative
该命令依赖gcc和zlib,需要先执行(不同环境需要的依赖不一样,可以先执行上面的编译命令,再根据报错添加所需依赖库)
sudo apt-get install gcc
sudo apt-get install zlib1g-dev
构建成功后,启动应用,执行
./target/spring-boot-build-docker
启动速度极快,几十毫秒
该方式无需联网,可以构建后通过Dockerfile继续构建docker镜像,但是需要保持构建环境和运行环境的类库兼容性。可以考虑通过同一个基础镜像构建构建镜像和运行镜像。
构建OCI镜像
./mvnw clean spring-boot:build-image -Pnative
通过docker-compose.yaml启动容器,同样也是极快启动
该方式是通过paketobuildpacks在docker容器中编译和构建镜像,能保证编译环境与运行环境的一致性,屏蔽了不同操作系统版本的影响。该方式是比较适合方式。但是构建过程中有些依赖需要从github上下载,有网络联通问题,且插件参数不能配置镜像或离线构建。
转载自:https://juejin.cn/post/7376926496366723098