拓冰建站拓冰建站
首页 / 资讯中心 / 正文

ARM64平台构建OpenOffice兼容Docker镜像:文档转换与中文乱码全解决

简介针对ARM64/aarch64架构下部署Office服务的需求面向企业开发与运维人员由于OpenOffice在国产化环境下适配不理想这里提供一套基于LibreOffice的Docker镜像制作文件使服务启动方式与OpenOffice保持一致便于平滑迁移。压缩包含15个文件、约644.27MB涵盖Dockerfile-arm构建脚本、LibreOffice的tar镜像、启动脚本以及11个中文字体文件ttf/ttc覆盖从镜像构建到容器运行的关键部件。目前已有1172人学习/下载说明该方案在ARM平台具备实际参考价值。通过这套文件用户可快速打造支持ARM64的LibreOffice容器环境内置常见中文字体避免文档显示乱码同时复用原有调用接口有效降低国产化迁移中的适配成本与维护复杂度。 上周同事把一个烫手山芋丢给我内网那批arm64服务器上要跑一个文档转换服务把OA系统里的Word、PPT批量转成PDF还点名要用OpenOffice。我第一反应是上Docker Hub搜一下现成镜像结果所有标着OpenOffice的镜像平台架构清一色amd64。往arm64机器上一拉直接报exec format error。折腾了一下午我决定自己做一个能在arm64上运行的OpenOffice风格Docker镜像顺带把中文变框框的坑也填了。这篇文章就是完整的制作过程包含可以直接抄的Dockerfile、构建命令、验证方法和排错思路适合需要在树莓派、鲲鹏、飞腾、Apple Silicon或者AWS Graviton这类arm64环境里跑文档转换的开发和运维朋友。1. 为什么偏要在arm64上折腾OpenOffice镜像1.1 文档转换服务是刚需很多业务系统都有这种需求用户上传Word、PPT、TXT系统后台自动转成PDF方便在线预览和归档。实现这个能力最常见的方式就是调用OpenOffice/LibreOffice的headless模式一条命令完成转换。这类服务通常部署在服务器上之前大家买的服务器基本都是x86_64架构随便拉一个镜像就能跑。但这两年情况变了。便宜又省电的arm64服务器越来越多云厂商的arm实例价格也更低很多公司开始把文档处理这种CPU密集型任务往arm64上迁。这时候问题就来了OpenOffice/LibreOffice这类老牌办公软件官方对arm64 Linux的支持非常滞后Docker Hub上能搜到的镜像几乎全是给x86准备的。1.2 官方包和现成镜像都不友好Apache OpenOffice官方目前只发布x86_64的deb和rpm二进制包没有提供arm64版本。这意味着你想在arm64机器上装官方原版OpenOffice连安装包都拿不到。Docker Hub上那些openoffice镜像要么是个人打包的老版本要么是基于Debian的amd64构建没有一个能在arm64上开箱即用。所以我只能自己动手做一个针对arm64架构的镜像。1.3 先说实话arm64上更推荐用LibreOffice兼容实现标题写的是OpenOffice但这里必须先把丑话说在前面Apache OpenOffice官方没有arm64二进制包而Linux发行版软件源里OpenOffice的位置基本都被LibreOffice替代了。LibreOffice是OpenOffice的社区分支命令行工具soffice、文件格式、UNO API都保持着高度兼容绝大多数依赖OpenOffice做文档转换的项目换到LibreOffice只是换了个包名而已。所以下面这份镜像实际安装的是LibreOffice但对外完全可以用OpenOffice的方式调用soffice命令业务代码一行都不用改。如果你的需求是能转文档、生成PDF这条路线最稳如果公司有硬性合规要求必须用Apache OpenOffice品牌那就要自行从源码交叉编译成本高得多不建议普通团队尝试。2. x86镜像在arm64环境里的三大拦路虎动手做镜像之前先搞清楚这些坑是怎么来的后面排错才不慌。2.1 exec format error架构不相同Docker镜像里的二进制文件是有CPU架构属性的。x86_64的二进制在arm64内核上无法直接执行内核只认aarch64格式的可执行文件。所以在arm64机器上跑amd64镜像容器一启动就报exec format error这是最常见的第一道坎。解决思路只有一个构建arm64原生镜像。2.2 qemu模拟慢到怀疑人生有些朋友会说我直接让Docker用qemu用户态模拟去跑x86容器不就行了我劝你冷静。OpenOffice本身就是重型软件启动要加载JVM、初始化一堆组件你再叠一层qemu指令翻译CPU占用直接拉满一个500KB的docx转PDF可能要等十几秒。批量任务一开服务器直接卡成PPT。所以别走这条路老老实实构建arm64原生镜像才是正解。2.3 确认你的arm64平台状态在开始构建前建议先确认环境避免做到一半才发现平台判断错误uname -m # 输出 aarch64 说明是arm64 docker version --format {{.Server.Arch}} # 输出 arm64 说明Docker守护进程跑在arm64上如果输出的是x86_64或amd64那你是在x86机器上做交叉构建需要跳到第6章看buildx的用法。如果已经是aarch64恭喜直接在目标机器上构建最省事。3. 可直接复制的Dockerfile逐段拆解3.1 基础镜像与环境变量FROM ubuntu:22.04 ENV DEBIAN_FRONTENDnoninteractive \ LANGC.UTF-8 \ HOME/tmp \ TZAsia/Shanghai基础镜像选了Ubuntu 22.04官方提供完整的arm64版本软件源里LibreOffice的版本也比较新。DEBIAN_FRONTENDnoninteractive是为了让apt在容器里不弹交互式配置界面LANGC.UTF-8避免locale问题HOME/tmp是因为soffice会在用户目录下写配置文件容器里默认root的HOME是/root如果这个目录不可写或被多个进程同时访问会有麻烦放到/tmp更安全。时区我顺手设成了Asia/Shanghai避免转换PDF时日期字段出现奇怪的时区偏差。3.2 软件包清单及理由RUN apt-get update apt-get install -y --no-install-recommends \ libreoffice-writer \ libreoffice-calc \ libreoffice-impress \ libreoffice-headless \ openjdk-11-jre-headless \ fontconfig \ fonts-noto-cjk \ fonts-wqy-zenhei \ libxinerama1 \ libxrandr2 \ libcups2 \ libdbus-glib-1-2 \ apt-get clean \ rm -rf /var/lib/apt/lists/*逐个说下为什么装这些libreoffice-writer、libreoffice-calc、libreoffice-impress对应Word、Excel、PPT三大类文档转换按需取舍不想转表格可以不装calc。libreoffice-headless无头模式支持包少了它soffice --headless会缺组件。openjdk-11-jre-headlessLibreOffice的很多滤镜和脚本功能依赖Java不装JRE某些文档转换会直接报无法加载JVM。fontconfig字体管理和缓存工具处理中文乱码必须靠它。fonts-noto-cjk、fonts-wqy-zenhei中文字体。不装中文字体转出来的PDF里中文大概率全是方框。libxinerama1、libxrandr2、libcups2、libdbus-glib-1-2LibreOffice虽然是headless但它在初始化时仍然会去加载X11相关库缺了会在启动阶段报error while loading shared libraries这类错误。这几个库是我实测踩坑才补上的。--no-install-recommends是为了控制镜像体积但代价是部分依赖需要自己手动列出。如果你构建后发现还有缺库报错用ldd $(which soffice)查一下缺失项补装即可。3.3 入口脚本应对并发和格式扩展直接拿soffice当ENTRYPOINT会有一个隐患多个转换任务并发执行时LibreOffice默认复用同一个用户配置目录会出现profile锁冲突报no suitable office installed或直接hang住。我建议用一个包装脚本解决。创建convert.sh#!/bin/bash set -e : ${CONVERT_TO:pdf} : ${OUTDIR:/workspace} exec soffice --headless --norestore --invisible \ -env:UserInstallationfile:///tmp/lo_profile_$$ \ --convert-to $CONVERT_TO \ --outdir $OUTDIR \ $脚本里最关键的三个设计-env:UserInstallationfile:///tmp/lo_profile_$$用进程号PID生成独立的LibreOffice用户目录彻底避开并发锁冲突。这是我之前线上批量转文档翻过车之后才想到的。CONVERT_TO环境变量默认转PDF想转docx、txt、odt时不用改镜像用-e CONVERT_TOdocx覆盖即可。OUTDIR环境变量默认输出到/workspace配合后续挂载目录使用。3.4 完整Dockerfile与使用方式把上面内容拼起来FROM ubuntu:22.04 ENV DEBIAN_FRONTENDnoninteractive \ LANGC.UTF-8 \ HOME/tmp \ TZAsia/Shanghai RUN apt-get update apt-get install -y --no-install-recommends \ libreoffice-writer \ libreoffice-calc \ libreoffice-impress \ libreoffice-headless \ openjdk-11-jre-headless \ fontconfig \ fonts-noto-cjk \ fonts-wqy-zenhei \ libxinerama1 \ libxrandr2 \ libcups2 \ libdbus-glib-1-2 \ apt-get clean \ rm -rf /var/lib/apt/lists/* RUN fc-cache -f COPY convert.sh /usr/local/bin/convert.sh RUN chmod x /usr/local/bin/convert.sh WORKDIR /workspace ENTRYPOINT [/usr/local/bin/convert.sh]使用方式就很简单了docker build -t office-arm64 . docker run --rm -v $(pwd)/testdata:/workspace office-arm64 测试文档.docx执行后PDF会直接出现在宿主机testdata目录下和原文档同名。如果文件名里有空格记得加引号。4. 构建、验证与常见报错对照4.1 构建镜像在已经确认是arm64的机器上执行docker build -t office-arm64 .首次构建需要下载Ubuntu基础镜像和几百MB软件包耗时取决于网络。如果apt源慢可以在apt-get update之前换成国内软件源镜像把/etc/apt/sources.list替换成对应的源地址。这一步能明显提升构建速度。4.2 用真实文档验证构建完成后强烈建议准备一份真实的docx文档验证而不是只转个txt。文档里最好包含中文、英文、表格、图片各来一点能一次性暴露字体和组件缺失问题。mkdir -p testdata # 把 testdata/测试文档.docx 放进去 docker run --rm -v $(pwd)/testdata:/workspace office-arm64 测试文档.docx ls -la testdata/看到测试文档.pdf生成并且用预览工具打开中文显示正常镜像就基本可用了。4.3 常见报错对照报错信息原因解决办法exec format error在arm64上跑了amd64镜像重新构建arm64镜像不要用qemu模拟E: Unable to locate package libreoffice-writerapt源里找不到软件包先apt-get update确认用的是Ubuntu/Debian完整源别用精简基础镜像soffice: error while loading shared libraries: libXinerama.so.1缺少X11相关库补装libxinerama1 libxrandr2 libcups2 libdbus-glib-1-2no suitable office installed并发任务共用profile导致锁冲突改用独立UserInstallation目录参考上文convert.sh转换后PDF中文全变方框容器里没有中文字体安装fonts-noto-cjk并执行fc-cache -f5. PDF汉字显示为框框的完整排查链路这个坑太经典了值得单独拿出来讲。虽然镜像里已经装了中文字体但你没法保证业务方上传的每个文档都用容器里存在的字体。下面是一套完整的排查链路。5.1 第一现场检查容器字体列表先确认容器里到底有没有中文字体docker run --rm office-arm64 fc-list :langzh如果输出为空说明系统里没有任何中文字体转PDF必然出现方框。解决办法就是装字体前面Dockerfile里的fonts-noto-cjk和fonts-wqy-zenhei已经解决了这个问题。如果字体列表里有Noto CJK和文泉驿但转出来的PDF中文依然是框框继续往下查。5.2 fontconfig替换缺失字体很多从Windows上传的文档字体用的是宋体、微软雅黑、SimSun这些字体名而容器里根本没有这些字体。LibreOffice找不到对应字体时会退回默认字体但这个回退机制在字体配置不完善时就会渲染成方框。解法是在容器里做一层fontconfig字体替换把Windows常见字体映射到我们已经安装的中文字体上。新建local.conf?xml version1.0? !DOCTYPE fontconfig SYSTEM fonts.dtd fontconfig match targetpattern test namefamilystringSimSun/string/test edit namefamily modeprepend bindingstrong stringNoto Serif CJK SC/string /edit /match match targetpattern test namefamilystring宋体/string/test edit namefamily modeprepend bindingstrong stringNoto Serif CJK SC/string /edit /match match targetpattern test namefamilystring微软雅黑/string/test edit namefamily modeprepend bindingstrong stringNoto Sans CJK SC/string /edit /match /fontconfig把这个文件复制进镜像的/etc/fonts/local.conf然后重新生成字体缓存docker cp local.conf office-arm64:/etc/fonts/local.conf # 或者直接写进Dockerfile # COPY local.conf /etc/fonts/local.conf docker run --rm office-arm64 fc-cache -f字体替换的逻辑是文档请求宋体时fontconfig会把它替换成Noto Serif CJK SC渲染。这样即使原文档指定了Windows字体转出来的PDF也能正常显示中文。5.3 验证字体是否嵌入PDF完成替换后重新转换测试文档然后用pdffonts命令检查生成PDF内嵌的字体pdffonts 测试文档.pdf重点看输出里有没有包含CJK或WenQuanYi字样的字体名。如果有说明中文字体已经正常嵌入如果显示的是空白或ID说明字体缺失问题依然存在。pdffonts来自poppler-utils宿主机没有就装一个或者直接在容器镜像里加装也行。经验之谈生产环境别依赖文档里刚好用到了容器字体这种运气。直接把上面的local.conf打进镜像一劳永逸。6. 在x86开发机上构建arm64镜像的两种方式很多人的开发机是x86笔记本但部署目标是arm64服务器。这种情况下有两种构建思路。6.1 方式一Docker buildx binfmt全模拟构建这是最常用的交叉构建方案。先创建多架构构建器docker buildx create --name multiarch --use docker run --privileged --rm tonistiigi/binfmt --install all第一条命令是让Docker支持多平台构建第二条命令是在当前机器注册QEMU用户态模拟器。之后就可以指定目标平台构建docker buildx build --platform linux/arm64 -t office-arm64:latest --load .--load会把构建好的arm64镜像导入当前Docker方便本地调试。但要注意如果你在x86机器上用--load拿到arm64镜像直接运行还是会报exec format error因为本机内核不认arm64二进制。这个镜像需要推到镜像仓库再到arm64服务器上拉取运行。这里有个体验教训buildx交叉构建时apt的下载和执行都是在QEMU模拟下进行的速度比原生构建慢不少。如果apt update或安装包时报奇怪的段错误多为模拟器兼容问题多试几次或者换一个Debian系基础镜像往往能解决。6.2 方式二直接在arm64机器上构建最省心的方法是直接在arm64服务器上构建镜像。哪怕是一台最低配的云主机原生构建速度都比x86 QEMU模拟快得多。我现在的标准流程是在x86开发机上写好Dockerfile和convert.shpush到Git仓库然后在arm64构建机上拉代码直接docker build全程不折腾模拟器。如果公司没有arm64构建机用云厂商的arm64按量付费实例临时起一台也行构建完销毁成本很低。6.3 推送多架构镜像如果你想把镜像同时提供给amd64和arm64的用户buildx可以一次构建并推送多平台镜像docker buildx build --platform linux/amd64,linux/arm64 \ -t yourname/office-arm64:latest \ --push .这样用户拉取时Docker会自动根据当前机器架构拉取对应平台层一个镜像标签通吃两种架构。这对做开源镜像是很友好的方案。这次折腾下来最大的体会是在arm64上做OpenOffice镜像真正的难点不在软件安装本身而在官方二进制缺失、并发profile锁冲突、中文字体缺失这三个暗坑。先把这三个问题想清楚Dockerfile反而五分钟就能写完。如果你也在做类似的文档转换服务建议上生产之前把字体替换配置直接打进镜像并用独立UserInstallation目录跑并发任务这两个动作能帮你少挨两顿加班。后面我还会在镜像上把常用的文件转换API封装一层到时候再补一篇。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门