简介这份资源面向需要在 ARM64aarch64服务器或国产化环境中部署文档转换服务的开发者与运维人员针对 OpenOffice 长期缺乏 ARM 架构适配、国产化支持不友好的痛点提供了一套可自行构建 Docker 镜像的完整制作文件用 LibreOffice 作为替代方案启动方式与 OpenOffice 保持一致解压即可使用。压缩包共 15 个文件约 644.27MB包含 7 个 ttf 与 4 个 ttc 中文字体、1 个 Dockerfile-arm、1 个构建脚本 bat、1 个启动脚本 sh 以及 1 个 libreoffice.tar 主程序包覆盖镜像构建、字体配置与服务启动所需的关键环节。目前已有 1177 人学习下载。借助这些文件读者可快速完成 ARM64 环境下 LibreOffice 镜像的定制与部署解决中文文档转换的字体缺失问题并参考配套文档说明排查构建与运行中的常见问题适合需要落地国产化文档处理方案的团队直接复用。1. 在 arm64 服务器上跑 OpenOffice为什么官方镜像靠不住得自己造手里有一台鲲鹏、飞腾或者 Ampere 的 arm64 服务器业务侧要批量把 Word、Excel 转成 PDF第一反应通常是docker pull一个现成的 OpenOffice 镜像。真去 Docker Hub 上翻一圈就会发现能用的基本都是 x86_64 架构拉下来docker run直接报exec format error容器起都起不来。这不是配置问题是镜像里的二进制和你的 CPU 指令集对不上。arm64 和 x64 的区别不只是寄存器宽度指令编码、系统调用约定、动态链接器路径全都不一样x86 的 ELF 文件在 arm64 内核上根本没法执行。所以「openoffice 在 arm64 环境下运行的 docker 镜像包制作文件」这件事本质是自己写一套 Dockerfile在 arm64 基础镜像里把 OpenOffice 装好、把无头模式调通、把中文字体补齐最后产出一个能直接docker run的镜像。适合谁适合手上已经有 arm64 机器、需要文档转换服务、又不想为这事单独买一台 x86 的运维和后台开发。下面按我实际做过的路径从基础镜像选型一路讲到镜像瘦身和验证。2. 基础镜像选型与 OpenOffice 安装从零写出可构建的 Dockerfile2.1 为什么选 Debian/Ubuntu 的 arm64 变体而不是 Alpine基础镜像这一步选错后面全是坑。Alpine 体积小是事实但它用 musl libc而 OpenOffice 及其依赖的 Java 运行时、字体配置工具链基本是按 glibc 编译的。你在 Alpine 上装 OpenOffice要么找不到包要么装上了运行时报Error loading shared library libc.musl。我一般直接用debian:bookworm-slim或ubuntu:22.04的 arm64 版本这两个在 arm64 上的软件源完整apt能直接拉到 OpenOffice 的包。选 Debian 还是 Ubuntu看你的团队习惯。Debian bookworm 的 arm64 源里包名是libreofficeOpenOffice 和 LibreOffice 在包管理层面已经合并了openoffice这个包名在新版源里基本找不到。这是个关键认知现在说的 OpenOffice 镜像实际装的是 LibreOffice命令行工具叫soffice兼容 OpenOffice 的文档格式和大部分调用方式。如果你死磕 Apache OpenOffice 原版得去官网下 arm64 的 deb 包手动装依赖处理会麻烦很多除非有明确的版本兼容要求否则没必要。先确认你的构建机架构别在 x86 上构建完推到 arm64 上才发现跑不了uname -m # 输出 aarch64 说明当前就是 arm64 环境 # 输出 x86_64 说明你在 x86 机器上需要交叉构建或换机器如果构建机是 x86可以用 QEMU 模拟 arm64 来构建这就是热搜里常提的 qemu 模拟 arm64。但模拟构建慢而且某些包安装时的 post-install 脚本在模拟环境下会出玄学问题。我的血泪经验是能找一台真 arm64 机器构建就别用 QEMU实在没有再用docker buildx配合 QEMU。2.2 一份能直接构建的 Dockerfile下面这份 Dockerfile 是我在 Debian bookworm arm64 上验证过的装 LibreOffice、中文字体、无头运行依赖一次构建成功# 使用 arm64 架构的 debian slim 基础镜像 FROM debian:bookworm-slim # 设置非交互模式避免 apt 安装时卡在配置界面 ENV DEBIAN_FRONTENDnoninteractive # 设置时区和语言环境 ENV TZAsia/Shanghai ENV LANGC.UTF-8 # 替换为国内源加速按你的网络环境决定是否保留 RUN sed -i s|deb.debian.org|mirrors.aliyun.com|g /etc/apt/sources.list.d/debian.sources 2/dev/null || true # 安装 LibreOffice 核心组件、中文字体、无头运行依赖 RUN apt-get update apt-get install -y --no-install-recommends \ libreoffice-writer \ libreoffice-calc \ libreoffice-impress \ libreoffice-core \ fonts-wqy-zenhei \ fonts-wqy-microhei \ fonts-noto-cjk \ fontconfig \ default-jre-headless \ fc-cache -fv \ apt-get clean \ rm -rf /var/lib/apt/lists/* # 创建非 root 用户运行避免权限问题 RUN useradd -m -u 1000 -s /bin/bash office \ mkdir -p /home/office/work \ chown -R office:office /home/office USER office WORKDIR /home/office/work # 默认启动一个常驻进程方便 docker exec 进去调用 CMD [tail, -f, /dev/null]这段 Dockerfile 有几个点要解释。--no-install-recommends是必须的不加的话 apt 会拉一堆图形界面相关的包镜像体积能翻两三倍而我们在无头环境里根本用不到。fonts-wqy-zenhei和fonts-noto-cjk是中文文档转换的关键不装的话转出来的 PDF 里中文全是方块这个坑后面还会细说。default-jre-headless是因为 LibreOffice 的部分转换功能依赖 Java装 headless 版本不拖图形库。fc-cache -fv这步别省它刷新字体缓存让 LibreOffice 能识别到刚装的中文字体。我见过有人装完字体没刷缓存转换时死活找不到字体排查半天。2.3 构建命令与架构确认构建时显式指定平台避免构建机架构和镜像架构不一致# 在 arm64 机器上直接构建 docker build -t openoffice-arm64:1.0 . # 如果在 x86 机器上交叉构建用 buildx docker buildx build --platform linux/arm64 -t openoffice-arm64:1.0 --load .构建完成后验证镜像架构docker inspect openoffice-arm64:1.0 --format {{.Architecture}} # 期望输出 arm64如果输出amd64说明构建时平台没指定对这个镜像推到 arm64 机器上照样跑不起来。这一步是很多人翻车的地方构建日志里不报错但架构就是错的。3. 无头模式调通与文档转换让 soffice 在容器里真正干活3.1 无头模式启动参数与用户配置目录OpenOffice/LibreOffice 在无头模式下运行第一次启动会尝试创建用户配置目录。如果容器里用的是 root 或者 HOME 目录不可写就会报javaldx: Could not find a Java Runtime Environment或者直接卡住。上面 Dockerfile 里建了office用户并设了WORKDIR就是为了避开这个。转换命令的核心是soffice --headless但直接跑经常遇到「第一次转换成功第二次卡死」的问题。原因是 LibreOffice 会复用用户配置目录里的锁文件并发或连续调用时锁没释放。解决办法是每次转换指定独立的用户配置目录soffice --headless \ --norestore \ --nologo \ --nolockcheck \ -env:UserInstallationfile:///tmp/lo_profile_$$ \ --convert-to pdf \ --outdir /home/office/work/output \ /home/office/work/input.docx-env:UserInstallation指向一个临时目录$$是当前进程 PID保证每次调用都是干净的环境。--norestore禁止崩溃恢复弹窗--nologo去掉启动画面--nolockcheck跳过锁检查。这几个参数加上连续转换基本不会卡。3.2 用 Python 封装批量转换服务实际业务里不会手动敲命令一般用 Python 包一层。下面这个脚本处理单文件和批量目录带超时和错误捕获import subprocess import os import uuid import logging logging.basicConfig(levellogging.INFO) logger logging.getLogger(__name__) def convert_to_pdf(input_path, output_dir, timeout120): 将单个文档转换为 PDF返回输出文件路径或 None if not os.path.exists(input_path): logger.error(f输入文件不存在: {input_path}) return None # 每次转换用独立的用户配置目录避免锁冲突 profile_dir f/tmp/lo_profile_{uuid.uuid4().hex} os.makedirs(profile_dir, exist_okTrue) cmd [ soffice, --headless, --norestore, --nologo, --nolockcheck, f-env:UserInstallationfile://{profile_dir}, --convert-to, pdf, --outdir, output_dir, input_path ] try: result subprocess.run( cmd, capture_outputTrue, textTrue, timeouttimeout ) if result.returncode ! 0: logger.error(f转换失败: {result.stderr}) return None # 输出文件名与输入同名扩展名换成 pdf base_name os.path.splitext(os.path.basename(input_path))[0] output_path os.path.join(output_dir, f{base_name}.pdf) if os.path.exists(output_path): logger.info(f转换成功: {output_path}) return output_path else: logger.error(转换命令返回成功但输出文件不存在) return None except subprocess.TimeoutExpired: logger.error(f转换超时: {input_path}) return None finally: # 清理临时配置目录 subprocess.run([rm, -rf, profile_dir], checkFalse) if __name__ __main__: import sys if len(sys.argv) 3: print(用法: python convert.py 输入文件 输出目录) sys.exit(1) convert_to_pdf(sys.argv[1], sys.argv[2])这个脚本的关键在timeout参数和finally里的清理。LibreOffice 偶尔会因为文档损坏卡死没有超时机制的话整个服务就挂住了。uuid生成独立配置目录比用 PID 更保险因为容器里 PID 可能重复。3.3 参数说明与常见调用差异参数作用不设置的后果--headless无界面模式容器里没有 X11直接报错退出--norestore禁止崩溃恢复文档损坏时弹窗等待进程卡死--nolockcheck跳过锁文件检查并发转换时互相阻塞-env:UserInstallation指定用户配置目录连续转换第二次开始卡死--convert-to pdf指定输出格式默认可能输出 odt 或其他格式--convert-to后面还能跟过滤器参数比如--convert-to pdf:writer_pdf_Export强制用 Writer 的 PDF 导出器。一般不用指定LibreOffice 会根据输入文件类型自动选。但如果遇到 Excel 转 PDF 排版错乱可以试试显式指定 Calc 的导出器。4. 避坑与排查arm64 下做 OpenOffice 镜像最容易翻车的五件事4.1 转换出来的 PDF 中文全是方块现象文档转换成功PDF 能打开但所有中文显示为方块或空白。原因容器里没有中文字体或者装了字体但没刷新缓存。LibreOffice 找不到对应字体时不会报错直接渲染成方块。解决Dockerfile 里装fonts-wqy-zenhei、fonts-wqy-microhei、fonts-noto-cjk装完执行fc-cache -fv。验证方法是进容器跑fc-list :langzh能列出中文字体才算装好。如果还不行检查文档里用的字体名有些 Windows 文档用「宋体」「黑体」Linux 下对应的是「SimSun」「SimHei」需要装fonts-arphic-uming之类的兼容字体或者用 fontconfig 做字体映射。4.2 容器启动报 exec format error现象docker run直接报exec format error容器秒退。原因镜像架构和宿主机不匹配。在 x86 上构建的镜像默认是 amd64推到 arm64 机器上跑不了。解决构建时加--platform linux/arm64或者直接在 arm64 机器上构建。构建完用docker inspect确认Architecture字段是arm64。用 QEMU 模拟构建的镜像虽然架构标记是 arm64但某些底层库可能有兼容问题优先用真机构建。4.3 连续转换第二个文件就卡死现象第一个文档转换正常第二个开始进程不退出CPU 占用低像是卡在等待。原因LibreOffice 复用用户配置目录第一个进程退出时锁文件没清理干净第二个进程启动时在等锁。解决每次转换用独立的-env:UserInstallation目录用 UUID 或时间戳命名转换完清理掉。不要图省事共用一个配置目录并发场景下必卡。4.4 镜像体积超过 2GB现象构建完docker images一看镜像 2GB 多推送到仓库慢拉取也慢。原因apt-get install没加--no-install-recommends拉了一堆图形界面和推荐包或者没清理/var/lib/apt/lists。解决安装时加--no-install-recommends装完apt-get clean rm -rf /var/lib/apt/lists/*。只装需要的组件比如只要转 Word 就装libreoffice-writer不用装全套。这样能把镜像压到 600MB 左右。4.5 转换大文件时内存暴涨被 OOM Kill现象转换几十页的文档时容器被系统杀掉dmesg里能看到 OOM 记录。原因LibreOffice 转换大文档时内存占用会飙升容器默认没有内存限制但宿主机内存不够时内核会杀进程。解决给容器设内存限制并留足余量比如docker run -m 2g。同时在应用层限制单次转换的文件大小和页数超大文档拆分处理。Java 堆内存也可以调设JAVA_OPTS-Xmx512m限制 JRE 占用。5. 镜像瘦身与多阶段构建把 2GB 压到 600MB 的具体手法镜像体积这事构建时不在意推仓库和拉取时就是折磨。我一般用多阶段构建把编译和运行分开。OpenOffice 本身不需要编译但字体缓存和依赖清理可以在单独阶段做最终镜像只保留运行时必需的文件。# 第一阶段安装和准备 FROM debian:bookworm-slim AS builder ENV DEBIAN_FRONTENDnoninteractive RUN apt-get update apt-get install -y --no-install-recommends \ libreoffice-writer \ libreoffice-calc \ fonts-wqy-zenhei \ fonts-noto-cjk \ fontconfig \ fc-cache -fv \ apt-get clean \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* # 第二阶段只复制运行时需要的文件 FROM debian:bookworm-slim # 从构建阶段复制 LibreOffice 和字体 COPY --frombuilder /usr/lib/libreoffice /usr/lib/libreoffice COPY --frombuilder /usr/bin/soffice /usr/bin/soffice COPY --frombuilder /usr/share/fonts /usr/share/fonts COPY --frombuilder /etc/fonts /etc/fonts # 安装运行时最小依赖 RUN apt-get update apt-get install -y --no-install-recommends \ libxinerama1 libxrender1 libxext6 libsm6 \ fc-cache -fv \ apt-get clean \ rm -rf /var/lib/apt/lists/* RUN useradd -m -u 1000 office USER office WORKDIR /home/office/work CMD [tail, -f, /dev/null]多阶段构建的收益在于第一阶段装的编译工具、apt 缓存、临时文件都不会进最终镜像。COPY --frombuilder只拿运行时真正需要的目录。注意soffice是个脚本它依赖/usr/lib/libreoffice下的实际二进制所以这两个都要复制。字体目录和 fontconfig 配置也要带上否则中文又变方块。瘦身之后验证功能是否完整别为了小体积把功能砍没了# 构建瘦身版 docker build -t openoffice-arm64:slim . # 跑一个转换测试 docker run --rm -v $(pwd)/test:/work openoffice-arm64:slim \ soffice --headless --convert-to pdf --outdir /work /work/test.docx # 检查输出 PDF 是否正常中文是否显示 ls -lh test/test.pdf如果转换报错说缺库用ldd /usr/lib/libreoffice/program/soffice.bin看缺哪个动态库补装对应的libxxx包。这个过程可能要迭代两三次但每次都能砍掉几百 MB。最后说个习惯我做完镜像一定会跑一个包含中文、表格、图片的测试文档确认转换结果和 x86 环境下一致。arm64 上 LibreOffice 的渲染引擎和 x86 是同一套源码编译的理论上结果一致但字体和库版本差异偶尔会导致排版偏移。每次改 Dockerfile 都重新跑一遍这个测试比事后排查省事得多。希望帮到你。本文还有配套的精品资源点击获取