Spring Boot Native构建Docker镜像无法访问src/main/resources文件
问题:Spring Boot Native Docker镜像无法读取resources下的文件
背景
目标是构建一个可读取src/main/resources目录下文件的Spring Boot Native应用。
pom.xml配置
<properties> <java.version>17</java.version> </properties> <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> <env> <!-- 确保`mvn spring-boot:build-image`使用项目定义的Java版本 --> <BP_JVM_VERSION>${java.version}</BP_JVM_VERSION> <!-- 未闭合标签 --> <profiles> <!-- mvn [goal] -Pnative --> <profile> <id>native</id> <build> <plugins> <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> <executions> <execution> <id>build-native</id> <goals> <goal>compile-no-fork</goal> </goals> <phase>package</phase> <configuration> <!-- Native镜像默认不包含资源,因此添加该配置 --> <buildArgs>-H:IncludeResources=.*txt$</buildArgs> <!-- 未闭合标签 -->
文件读取代码
private static Stream<String> readFileFromResourcesDirectory(String filename) { String fileString; try (InputStream inputStream = DemoController.class.getClassLoader() .getResourceAsStream(filename)) { if (inputStream == null) throw new Exception("Can't find file " + filename + " in /resources."); fileString = IOUtils.toString(inputStream, UTF_8); } catch (Exception e) { throw new RuntimeException("Issue reading or parsing file " + filename + "\n" + e.getMessage()); } return Arrays.stream(fileString.split("\n")); }
异常信息
运行mvn spring-boot:build-image -Pnative构建的Docker镜像时触发异常:
java.lang.RuntimeException: Issue reading or parsing file foo.txt Can't find file foo.txt in /resources.
测试结果
- 未使用
-Pnative构建的Docker镜像运行正常 - 使用
mvn package -Pnative构建的本地Native可执行文件运行正常 - 使用
-Pnative构建的Docker镜像运行异常
镜像构建日志片段
日志显示本地Native构建已执行指定参数:
[INFO] Executing: /home/tco/graalvm/graalvm-ce-java17-22.3.1/bin/native-image (...) -H:IncludeResources=.*txt$
原因分析与解决方案
原因
你在native-maven-plugin的native profile中配置的-H:IncludeResources=.*txt$仅对本地Native可执行文件构建(mvn package -Pnative)生效。但使用spring-boot:build-image -Pnative构建Docker镜像时,Spring Boot的Buildpacks构建流程不会复用该配置,导致镜像内的Native可执行文件未包含指定的txt资源。
解决方案
需要通过spring-boot-maven-plugin的image配置,将Native Image构建参数传递给Docker构建流程,具体是添加BP_NATIVE_IMAGE_BUILD_ARGUMENTS环境变量:
修改spring-boot-maven-plugin的配置部分:
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <image> <env> <!-- 确保构建镜像使用项目定义的Java版本 --> <BP_JVM_VERSION>${java.version}</BP_JVM_VERSION> <!-- 传递Native Image构建参数,包含所有txt后缀的资源 --> <BP_NATIVE_IMAGE_BUILD_ARGUMENTS>-H:IncludeResources=.*txt$</BP_NATIVE_IMAGE_BUILD_ARGUMENTS> </env> </image> </configuration> </plugin>
BP_NATIVE_IMAGE_BUILD_ARGUMENTS是Spring Boot Buildpacks专门用于传递Native Image构建参数的环境变量,配置后Docker镜像构建过程会自动将该参数传给GraalVM的native-image命令,确保txt资源被正确包含到镜像内的可执行文件中。
内容的提问来源于stack exchange,提问作者ThCollignon
相关产品推荐
相关产品推荐

