Docker化Spring Boot应用Excel导出字体依赖问题排查与解决
Spring Boot Docker化后Excel报表字体依赖问题解决记录
我开发的应用后端基于Spring Boot(Java 17)、前端基于ReactJS,使用Maven构建。本地Oracle JDK 17.0.4环境下报表功能正常,但Docker化后,Excel报表下载场景报错,后端日志显示java.lang.UnsatisfiedLinkError,提示无法加载字体系统依赖的libfontmanager.so及其依赖libfreetype.so.6。
原始Dockerfile
# === Stage 1: Build the Spring Boot app === FROM maven:3.6.3-openjdk-17 AS build WORKDIR /app COPY pom.xml . COPY src/ /app/src/ RUN mvn package -DskipTests # === Stage 2: Create the final Docker image === FROM openjdk:17-alpine WORKDIR /app COPY --from=build /app/target/backend-0.0.1-SNAPSHOT.jar app.jar # Set environment variables for MySQL configuration ENV MYSQL_HOST=localhost ENV MYSQL_PORT=****** //Omitted ENV MYSQL_DATABASE=db ENV MYSQL_USERNAME=****** //Omitted ENV MYSQL_PASSWORD=************ //Omitted EXPOSE 8080 CMD ["java", "-jar", "app.jar"]
关键错误日志
错误1:缺失字体依赖库
2023-10-05T07:19:23.875Z ERROR 1 --- [nio-8080-exec-8] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed: java.lang.UnsatisfiedLinkError: /opt/openjdk-17/lib/libfontmanager.so: Error loading shared library libfreetype.so.6: No such file or directory (needed by /opt/openjdk-17/lib/libfontmanager.so)] with root cause java.lang.UnsatisfiedLinkError: /opt/openjdk-17/lib/libfontmanager.so: Error loading shared library libfreetype.so.6: No such file or directory (needed by /opt/openjdk-17/lib/libfontmanager.so) at java.base/jdk.internal.loader.NativeLibraries.load(Native Method) ~[na:na] at java.base/jdk.internal.loader.NativeLibraries$NativeLibraryImpl.open(NativeLibraries.java:383) ~[na:na] at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:227) ~[na:na] at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:169) ~[na:na] at java.base/jdk.internal.loader.NativeLibraries.findFromPaths(NativeLibraries.java:310) ~[na:na] at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:280) ~[na:na] at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2392) ~[na:na] at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:808) ~[na:na] at java.base/java.lang.System.loadLibrary(System.java:1893) ~[na:na] at java.desktop/sun.font.FontManagerNativeLibrary$1.run(FontManagerNativeLibrary.java:57) ~[na:na] at java.base/java.security.AccessController.doPrivileged(AccessController.java:312) ~[na:na] at java.desktop/sun.font.FontManagerNativeLibrary.<clinit>(FontManagerNativeLibrary.java:32) ~[na:na] at java.desktop/sun.font.SunFontManager$1.run(SunFontManager.java:270) ~[na:na] at java.desktop/sun.font.SunFontManager$1.run(SunFontManager.java:268) ~[na:na] at java.base/java.security.AccessController.doPrivileged(AccessController.java:312) ~[na:na] at java.desktop/sun.font.SunFontManager.<clinit>(SunFontManager.java:268) ~[na:na] at java.base/java.lang.Class.forName0(Native Method) ~[na:na] at java.base/java.lang.Class.forName(Class.java:466) ~[na:na] at java.desktop/sun.font.FontManagerFactory$1.run(FontManagerFactory.java:82) ~[na:na] at java.base/java.security.AccessController.doPrivileged(AccessController.java:312) ~[na:na] at java.desktop/sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:74) ~[na:na] at java.desktop/java.awt.Font.getFont2D(Font.java:526) ~[na:na] at java.desktop/java.awt.Font.canDisplayUpTo(Font.java:2279) ~[na:na] at java.desktop/java.awt.font.TextLayout.singleFont(TextLayout.java:469) ~[na:na] at java.desktop/java.awt.font.TextLayout.<init>(TextLayout.java:530) ~[na:na] at org.apache.poi.ss.util.SheetUtil.getDefaultCharWidth(SheetUtil.java:285) ~[poi-5.0.0.jar!/:5.0.0] at org.apache.poi.ss.util.SheetUtil.getColumnWidth(SheetUtil.java:259) ~[poi-5.0.0.jar!/:5.0.0] at org.apache.poi.ss.util.SheetUtil.getColumnWidth(SheetUtil.java:244) ~[poi-5.0.0.jar!/:5.0.0] at org.apache.poi.xssf.usermodel.XSSFSheet.autoSizeColumn(XSSFSheet.java:523) ~[poi-ooxml-5.0.0.jar!/:5.0.0] at org.apache.poi.xssf.usermodel.XSSFSheet.autoSizeColumn(XSSFSheet.java:505) ~[poi-ooxml-5.0.0.jar!/:5.0.0] at com.antarctica21.backend.forecasting.service.PlanService.saveWOSRZipExcelFile(PlanService.java:3352) ~[classes!/:0.0.1-SNAPSHOT] at com.antarctica21.backend.forecasting.service.PlanService.getWeekOversSalesExcelDetails(PlanService.java:3244) ~[classes!/:0.0.1-SNAPSHOT]
错误2:字体管理器初始化失败
java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11FontManager at java.base/java.lang.Class.forName0(Native Method) ~[na:na] at java.base/java.lang.Class.forName(Class.java:466) ~[na:na] at java.desktop/sun.font.FontManagerFactory$1.run(FontManagerFactory.java:82) ~[na:na] at java.base/java.security.AccessController.doPrivileged(AccessController.java:312) ~[na:na] at java.desktop/sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:74) ~[na:na] at java.desktop/java.awt.Font.getFont2D(Font.java:526) ~[na:na] at java.desktop/java.awt.Font.canDisplayUpTo(Font.java:2279) ~[na:na] at java.desktop/java.awt.font.TextLayout.singleFont(TextLayout.java:469) ~[na:na] at java.desktop/java.awt.font.TextLayout.<init>(TextLayout.java:530) ~[na:na] at org.apache.poi.ss.util.SheetUtil.getDefaultCharWidth(SheetUtil.java:285) ~[poi-5.0.0.jar!/:5.0.0] at org.apache.poi.ss.util.SheetUtil.getColumnWidth(SheetUtil.java:259) ~[poi-5.0.0.jar!/:5.0.0] at org.apache.poi.ss.util.SheetUtil.getColumnWidth(SheetUtil.java:244) ~[poi-5.0.0.jar!/:5.0.0] at org.apache.poi.xssf.usermodel.XSSFSheet.autoSizeColumn(XSSFSheet.java:523) ~[poi-ooxml-5.0.0.jar!/:5.0.0] at org.apache.poi.xssf.usermodel.XSSFSheet.autoSizeColumn(XSSFSheet.java:505) ~[poi-ooxml-5.0.0.jar!/:5.0.0] at com.antarctica21.backend.forecasting.service.PlanService.saveWOSRZipExcelFile(PlanService.java:3352) ~[classes!/:0.0.1-SNAPSHOT] at com.antarctica21.backend.forecasting.service.PlanService.getWeekOversSalesExcelDetails(PlanService.java:3244) ~[classes!/:0.0.1-SNAPSHOT] at com.antarctica21.backend.forecasting.service.PlanService.getWeekOversSalesExcelDetilsByCriteria(PlanService.java:541) ~[classes!/:0.0.1-SNAPSHOT] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na] at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.7.jar!/:6.0.7] at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698) ~[spring-aop-6.0.7.jar!/:6.0.7] at com.antarctica21.backend.forecasting.service.PlanService$$SpringCGLIB$$0.getWeekOversSalesExcelDetilsByCriteria(<generated>) ~[classes!/:0.0.1-SNAPSHOT] at com.antarctica21.backend.forecasting.controller.PlanController.getWeekOversSalesExcelDetilsByCriteria(PlanController.java:190) ~[classes!/:0.0.1-SNAPSHOT] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
问题解决过程
第一次更新:安装基础字体依赖并升级POI
针对OpenJDK Alpine镜像缺少字体依赖的问题,修改Dockerfile添加字体相关库:
# Install required libraries RUN apk add --no-cache freetype fontconfig
同时将Apache POI依赖升级至5.2.4版本:
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>5.2.4</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.2.4</version> </dependency>
此次更新修复了原始的UnsatisfiedLinkError,但出现新的字体配置异常:java.lang.NullPointerException: Cannot load from short array because "sun.awt.FontConfiguration.head" is null.
第二次更新:安装系统字体并配置
修改Dockerfile安装微软核心字体并更新字体配置,最终解决问题:
RUN apk add --no-cache msttcorefonts-installer fontconfig RUN update-ms-fonts
内容的提问来源于stack exchange,提问作者Gehan
相关产品推荐
相关产品推荐

