插件窝 干货文章 docker打包镜像后EasyExcel报错,dockerfile缺少字体的解决

docker打包镜像后EasyExcel报错,dockerfile缺少字体的解决

字体 方案 镜像 安装 277    来源:    2025-04-01

Docker打包镜像后EasyExcel报错:缺少字体解决方案

当使用Docker打包包含EasyExcel的Java应用时,可能会遇到字体相关的报错,这是因为基础Docker镜像通常不包含完整的中文字体库。以下是解决方案:

问题原因

EasyExcel在生成Excel文件时需要访问系统字体,而常见的Docker基础镜像(如openjdk)通常不包含完整字体库,导致报错:

java.awt.FontFormatException
或
Can't find font file

解决方案

方案1:安装字体到Docker镜像中

修改Dockerfile,添加字体安装步骤:

FROM openjdk:8-jdk-alpine

# 安装字体(针对Alpine Linux)
RUN apk add --no-cache ttf-dejavu fontconfig

# 或者针对Ubuntu基础镜像
# FROM openjdk:8
# RUN apt-get update && apt-get install -y fontconfig fonts-wqy-microhei && rm -rf /var/lib/apt/lists/*

# 复制应用程序
COPY target/your-app.jar app.jar

ENTRYPOINT ["java", "-jar", "/app.jar"]

方案2:使用包含字体的基础镜像

FROM adoptopenjdk/openjdk8:jdk8u292-b10-ubuntu

# 确保字体已安装
RUN apt-get update && apt-get install -y fontconfig fonts-wqy-microhei && rm -rf /var/lib/apt/lists/*

COPY target/your-app.jar app.jar

ENTRYPOINT ["java", "-jar", "/app.jar"]

方案3:手动添加特定字体文件

如果只需要特定字体,可以将字体文件添加到镜像中:

  1. 将字体文件(如simsun.ttf)放在项目resources/fonts目录下
  2. 修改Dockerfile:
FROM openjdk:8-jdk-alpine

# 创建字体目录并复制字体
RUN mkdir -p /usr/share/fonts
COPY src/main/resources/fonts/simsun.ttf /usr/share/fonts/

# 刷新字体缓存
RUN apk add --no-cache fontconfig && \
    fc-cache -fv

COPY target/your-app.jar app.jar

ENTRYPOINT ["java", "-jar", "/app.jar"]

方案4:禁用EasyExcel的字体检查(不推荐)

如果只是需要基本功能,可以在EasyExcel初始化时禁用字体检查:

EasyExcel.write(response.getOutputStream(), YourDataClass.class)
    .registerWriteHandler(new WriteHandler() {
        @Override
        public void sheet(int i, Sheet sheet) {}
        @Override
        public void row(int i, Row row) {}
        @Override
        public void cell(int i, Cell cell) {}
    })
    .autoCloseStream(true)
    .ignoreFontStyle(true)  // 忽略字体样式
    .sheet("Sheet1")
    .doWrite(dataList);

验证字体是否安装成功

可以在容器内运行以下命令验证:

docker exec -it your-container /bin/sh
fc-list

应该能看到已安装的字体列表。

最佳实践建议

  1. 对于生产环境,推荐使用方案1或方案2,安装完整的字体库
  2. 如果需要特定中文字体,使用方案3手动添加
  3. 方案4仅作为临时解决方案,不推荐在生产环境使用

选择哪种方案取决于你的具体需求和对镜像大小的限制。