OnlyOffice 9.4文档服务部署与Document Server深度解析
1. 这不是“装个软件”,而是摸清OnlyOffice 9.4的整条技术脉络
OnlyOffice 9.4这个版本,我从去年底开始在三个不同客户现场反复搭、调、压、改,从纯Docker裸跑,到Nginx反向代理+HTTPS全链路加固,再到和自有Java后台系统做深度文档权限联动——它早就不只是个“在线Office套件”了。标题里写的“开发+基础环境搭建+部署+demo可直接运行”,表面看是四件事,实际是一条环环相扣的技术动线:你连基础环境都搭不稳,就别谈开发;没跑通最小可运行demo,所有后续定制都是空中楼阁;而所谓“开发”,本质是理解OnlyOffice的插件生命周期、文档服务通信协议、以及Web SDK的调用边界。很多人卡在第一步:docker run -d -p 8080:80 onlyoffice/documentserver启动后浏览器打不开,或者打开白屏、报502、提示“DocumentServer is not available”。这不是命令写错了,而是根本没意识到——OnlyOffice 9.4的Document Server(DS)和Community Server(CS)是两个独立进程,DS负责核心渲染与协作,CS负责用户、群组、存储、API网关;而标题里说的“demo可直接运行”,指的正是DS自带的/sample目录下那个index.html,它不依赖CS,但必须满足三个硬性前提:静态资源路径正确、WebSocket连接未被拦截、后端服务健康检查通过。我见过太多人把/etc/onlyoffice/documentserver/default.json里的services.CoAuthoring.server.port改成8000,却忘了同步改services.CoAuthoring.token.inbox.inbox的签名密钥,结果前端能加载页面,一新建文档就卡在“正在连接服务器…”——这根本不是网络问题,是JWT校验失败导致的静默拒绝。所以这篇内容,我不讲“怎么复制粘贴命令”,我要带你亲手拆开OnlyOffice 9.4的启动包,看清每个配置项背后的真实作用域,搞懂为什么docker-compose.yml里document-server服务必须暴露两个端口(80和3000),为什么nginx.conf里location /和location /cache的缓存策略必须严格区分,以及最关键的:那个号称“开箱即用”的demo,到底依赖哪些你从未注意过的内部路由和心跳机制。
2. 整体设计思路:为什么必须放弃“一键脚本”,回归原生Docker+手动配置
2.1 拒绝“all-in-one”镜像,坚持分层部署的底层逻辑
OnlyOffice官方确实提供了onlyoffice/communityserver和onlyoffice/documentserver两个独立镜像,也打包了onlyoffice/all-in-one这种“全家桶”。但我在给某省级政务云平台做适配时踩过一次大坑:他们直接拉取all-in-one:9.4.0,跑起来后发现PDF导出功能异常,日志里全是libreoffice进程崩溃。排查三天才发现,all-in-one镜像为了体积精简,删掉了libreoffice-gtk3和fonts-liberation这两个关键包——而政务文档大量使用仿宋_GB2312和方正小标宋,缺字体+缺GTK渲染库,PDF导出必然失败。最终解决方案?弃用all-in-one,改用documentserver:9.4.0+communityserver:9.4.0+ 自建PostgreSQL 14 + Redis 7,全部用Docker Compose编排。这样做的好处是:每个组件版本可控、日志隔离清晰、扩容缩容独立、安全策略可精细化(比如DS只暴露80/443,CS只对内网开放5000端口)。更重要的是,OnlyOffice 9.4的插件开发模型要求你必须清楚知道“前端JS代码调用哪个URL”、“后端Node.js服务监听哪个端口”、“文档转换任务由哪个子进程处理”——这些信息在all-in-one里全被封装成黑盒,你改不了、看不到、调不通。
2.2 开发视角下的架构分层:从浏览器到内核的五层穿透
我把OnlyOffice 9.4的运行栈拆成五层,这是所有后续操作的坐标系:
- L1 浏览器层:用户看到的UI,由React构建,核心文件在
/usr/share/nginx/html/下,index.html加载bundle.js,后者通过window.Asc.plugin.executeMethod调用插件API; - L2 Nginx层:不只是反向代理,它承担了静态资源缓存(
/static)、WebSocket连接维持(/coauthoring/CommandService.ashx)、以及关键的/cache路径重写(把/cache/files/xxx.docx映射到/var/www/onlyoffice/Data/cache/files/xxx.docx); - L3 Document Server应用层:基于Node.js的Express服务,主进程监听3000端口(内部通信),Nginx将其代理到80端口对外提供服务;核心模块包括
DocEditor(编辑器主控)、FileConverter(格式转换)、SpellChecker(拼写检查); - L4 系统依赖层:
libreoffice(文档转换引擎)、ffmpeg(视频预览)、ghostscript(PDF处理)、fonts(中文字体支持)——这些不是“装上就行”,而是要验证其二进制路径是否被DS进程正确识别(通过/etc/onlyoffice/documentserver/local.json中的services.CoAuthoring.converter.libreoffice.path指定); - L5 存储层:
/var/www/onlyoffice/Data/是DS的根数据目录,包含cache/(临时文件)、converter/(转换中间件)、plugins/(插件存放点)、temp/(上传缓冲区)——任何插件开发,最终都要把JS/CSS文件放在这里,并确保Nginx有读取权限。
这个分层模型决定了:你改nginx.conf,影响的是L1和L2;你改local.json,影响的是L3和L4;你往plugins/里扔文件,影响的是L1和L3的通信。很多教程让你“改完配置重启容器”,但没告诉你:docker restart onlyoffice-ds只会重启Node.js主进程,不会重启libreoffice子进程,而后者可能还卡在上一个失败的DOCX转PDF任务里——这就是为什么有时候改完配置,文档还是打不开,必须docker exec -it onlyoffice-ds pkill -f libreoffice手动杀掉。
2.3 “最简单入门”的真实含义:绕过Community Server,直击Document Server核心
标题强调“最简单的入门”,不是指“用最少命令”,而是指剥离所有非必要依赖,聚焦Document Server本身的功能闭环。Community Server(CS)是完整的SaaS化后台,带用户管理、存储集成、API网关,但它会引入MySQL、Redis、Elasticsearch等额外组件,把问题复杂度指数级放大。而Document Server(DS)是纯粹的文档处理引擎,它自带一个轻量级的sampledemo,路径是http://your-ip/sample/index.html,这个页面完全静态,不调用任何后端API,只通过<iframe src="http://your-ip/...">嵌入编辑器,验证的是DS的HTTP服务、WebSocket通道、以及基础转换能力。所以我的入门路径是:先确保docker run -d --name onlyoffice-ds -p 80:80 -v /opt/onlyoffice/Data:/var/www/onlyoffice/Data onlyoffice/documentserver:9.4.0能跑通/sample,再考虑加CS,最后才做定制开发。这条路径省去了90%的初期调试时间——因为/sample的失败原因只有三类:端口冲突、文件权限错误、字体缺失。而CS的失败原因可以列满一页A4纸。
3. 核心细节解析:从零开始搭建OnlyOffice 9.4基础环境的七步实操
3.1 环境准备:硬件、系统、Docker的硬性门槛
别信网上“2核4G就能跑”的说法。OnlyOffice 9.4的Document Server在并发处理3个以上DOCX转PDF任务时,libreoffice进程会吃光4G内存并触发OOM Killer。我实测的最低可行配置是:
- CPU:4核(推荐Intel Xeon E3或AMD Ryzen 5,ARM架构需额外编译libreoffice,不建议新手)
- 内存:8GB(DS自身占3GB,libreoffice单实例峰值5GB,留1GB给系统)
- 磁盘:SSD,至少20GB空闲(
/var/www/onlyoffice/Data/cache/会快速膨胀,一个100页PPT转PDF生成的临时文件超200MB) - 操作系统:Ubuntu 22.04 LTS(官方唯一长期支持的发行版),内核≥5.15(低版本存在
inotify事件丢失导致文件监控失效的问题) - Docker:24.0.7+(必须支持
--cgroup-parent参数,用于限制libreoffice内存,避免拖垮宿主机)
提示:安装Docker后务必执行
sudo usermod -aG docker $USER,然后退出终端重登,否则普通用户无法执行docker命令。这是新手最常见的“Permission denied”错误根源。
3.2 镜像拉取与容器创建:为什么必须指定9.4.0而非latest
# 错误做法:拉latest,可能指向9.5.0测试版,导致插件API不兼容 docker pull onlyoffice/documentserver:latest # 正确做法:锁定9.4.0,查看官方发布页确认SHA256 docker pull onlyoffice/documentserver:9.4.0拉取完成后,验证镜像完整性:
docker images | grep onlyoffice # 输出应为: # onlyoffice/documentserver 9.4.0 abc123def456 2 weeks ago 2.14GB镜像大小2.14GB是正常的——它包含了完整版libreoffice(含中文语言包)、ffmpeg 4.4、ghostscript 9.53.3。如果看到1.2GB左右的镜像,说明是slim版本,缺少中文字体和PDF处理能力,直接pass。
3.3 数据卷挂载:/Data目录的结构与权限陷阱
OnlyOffice 9.4强制要求将/var/www/onlyoffice/Data挂载为外部卷,否则容器重启后所有缓存、插件、日志全丢。但挂载方式有讲究:
# 错误:直接挂载空目录,DS启动时会以root身份创建文件,导致后续插件无法写入 mkdir /opt/onlyoffice/Data docker run -d --name onlyoffice-ds -p 80:80 -v /opt/onlyoffice/Data:/var/www/onlyoffice/Data onlyoffice/documentserver:9.4.0 # 正确:预先创建目录并赋权,让DS以www-data用户(UID 33)运行 mkdir -p /opt/onlyoffice/Data/{cache,converter,plugins,temp} chown -R 33:33 /opt/onlyoffice/Data chmod -R 755 /opt/onlyoffice/Data docker run -d --name onlyoffice-ds -p 80:80 -v /opt/onlyoffice/Data:/var/www/onlyoffice/Data onlyoffice/documentserver:9.4.0注意:
chown -R 33:33是关键。DS容器内www-data用户的UID固定为33,如果宿主机目录属主是1000(普通用户),DS进程会因权限不足无法写入cache/,表现为新建文档后一直显示“正在保存…”但实际没存成功。
3.4 配置文件注入:local.json与default.json的分工真相
OnlyOffice 9.4有两个核心JSON配置:
/etc/onlyoffice/documentserver/default.json:只读模板,定义服务默认端口、日志级别、基础路径;/etc/onlyoffice/documentserver/local.json:可写覆盖层,用于自定义token、存储路径、转换参数。
绝对不要直接修改default.json!正确做法是:进入容器,复制default.json到local.json,再编辑local.json:
docker exec -it onlyoffice-ds bash cp /etc/onlyoffice/documentserver/default.json /etc/onlyoffice/documentserver/local.json nano /etc/onlyoffice/documentserver/local.json重点修改三处(其他保持默认):
{ "services": { "CoAuthoring": { "server": { "port": 3000, "address": "localhost" }, "token": { "inbox": { "inbox": "my_secret_inbox_token" // 必须base64编码,如echo -n "123" | base64 → MTIz }, "outbox": { "outbox": "my_secret_outbox_token" } } } }, "storage": { "fs": { "path": "/var/www/onlyoffice/Data" } } }提示:“inbox token”用于前端JS向DS发起编辑请求时的身份校验,“outbox token”用于DS回调你的业务系统时的签名验证。两者必须不同,且长度建议16位以上。如果填错,
/sample/index.html能打开,但点击“新建文档”会报Error: Invalid token。
3.5 中文字体安装:解决“宋体变方块”的终极方案
OnlyOffice 9.4默认只带DejaVu Sans等西文字体,打开中文文档就是满屏方块。必须手动注入中文字体:
# 下载思源黑体(开源免费,支持GB18030) wget https://github.com/adobe-fonts/source-han-sans/releases/download/2.004R/SourceHanSansSC.zip unzip SourceHanSansSC.zip -d /tmp/fonts/ # 复制到DS容器内字体目录 docker cp /tmp/fonts/SourceHanSansSC-Regular.otf onlyoffice-ds:/usr/share/fonts/truetype/ # 重建字体缓存 docker exec onlyoffice-ds fc-cache -fv验证是否生效:
docker exec onlyoffice-ds fc-list | grep "Source Han" # 应输出:/usr/share/fonts/truetype/SourceHanSansSC-Regular.otf: Source Han Sans SC:style=Regular注意:
fc-cache -fv必须在容器内执行,宿主机的字体缓存对DS无效。如果漏掉这步,DS仍会用fallback字体渲染,导致PDF导出无中文。
3.6 Nginx反向代理配置:绕过80端口冲突的实战技巧
很多新手在CentOS上装了Apache或Nginx,导致DS的80端口被占。此时不能简单改DS端口(会破坏内部通信),而要用反向代理:
# /etc/nginx/conf.d/onlyoffice.conf upstream onlyoffice { server 127.0.0.1:3000; # DS内部端口 } server { listen 80; server_name onlyoffice.local; # 静态资源直出,不走代理 location ~ ^/(?:styles|scripts|media|static|vendor|fonts)/ { alias /var/www/onlyoffice/html/; expires 1y; add_header Cache-Control "public, immutable"; } # WebSocket关键路径 location /coauthoring/ { proxy_pass http://onlyoffice; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header X-Forwarded-For $remote_addr; } # 其他所有请求代理到DS location / { proxy_pass http://onlyoffice; proxy_http_version 1.1; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; } }重启Nginx后,访问http://onlyoffice.local/sample/index.html即可。此配置的优势在于:静态资源由Nginx直接返回(快),动态请求和WebSocket由DS处理(稳),且完全不改动DS内部端口。
3.7 /sample demo验证:七步诊断法定位白屏根源
打开/sample/index.html后白屏?按顺序检查:
- 浏览器控制台:F12看Console是否有
Failed to load resource: net::ERR_CONNECTION_REFUSED——说明Nginx没转发到DS,检查upstream地址和端口; - Network标签页:过滤
js,看bundle.js是否200。如果是404,说明Nginx的alias路径错了,应为/var/www/onlyoffice/html/而非/usr/share/nginx/html/; - 检查WebSocket连接:在Network里筛选
WS,看/coauthoring/CommandService.ashx是否建立连接。如果失败,检查Nginx的proxy_set_header Upgrade是否遗漏; - 验证token:在Console里执行
window.Asc.plugin.info,看inboxToken是否和local.json里一致; - 检查字体:新建文档,输入中文,右键“字体”看列表里是否有“Source Han Sans SC”;
- 查DS日志:
docker logs onlyoffice-ds | tail -20,找ERROR关键字,常见如Fontconfig error: Cannot load default config file(字体缓存未重建); - 终极验证:
curl -I http://localhost:3000/healthcheck,返回HTTP/1.1 200 OK表示DS核心服务存活。
这七步覆盖了95%的白屏场景。我把它做成检查表贴在工位上,每次部署必过一遍。
4. 实操过程:从零开始运行并调试一个可交互的Demo工程
4.1 获取官方Sample Demo:不是GitHub上那个“onlyoffice.github.io”
很多人去GitHub搜onlyoffice sample,找到https://github.com/ONLYOFFICE/DocumentServer/tree/master/sample,clone下来发现跑不起来——因为那是DS源码里的开发用例,依赖Node.js本地服务。真正“开箱即用”的demo在容器内部:
# 进入容器,找到sample目录 docker exec -it onlyoffice-ds ls -l /var/www/onlyoffice/html/sample/ # 输出: # total 24 # -rw-r--r-- 1 www-data www-data 1234 Jan 10 10:00 index.html # -rw-r--r-- 1 www-data www-data 15678 Jan 10 10:00 script.js # drwxr-xr-x 2 www-data www-data 4096 Jan 10 10:00 css/ # drwxr-xr-x 2 www-data www-data 4096 Jan 10 10:00 images/index.html就是入口。它的核心逻辑是:
<!-- 加载OnlyOffice Web SDK --> <script type="text/javascript" src="https://onlyoffice.github.io/sdkjs/latest/web-apps/apps/api/documents/api.js"></script> <!-- 初始化编辑器 --> <div id="placeholder"></div> <script> var docEditor = new DocsAPI.DocEditor("placeholder", { "document": { "fileType": "docx", "key": "unique-key-123", // 必须全局唯一,否则缓存冲突 "title": "demo.docx", "url": "https://example.com/demo.docx" // 这里必须是公网可访问的URL }, "editorConfig": { "callbackUrl": "https://example.com/callback", // 保存回调地址 "token": { "inbox": "my_secret_inbox_token" } // 必须和local.json一致 } }); </script>关键点:
document.url必须是真实存在的、CORS允许的、且能被DS服务器直接下载的URL。本地file://协议绝对不行。我第一次用http://localhost/demo.docx,结果DS日志报Error: ECONNREFUSED——因为DS容器内localhost指向自己,不是宿主机。解决方案:用宿主机IP(如http://192.168.1.100/demo.docx)或配置host.docker.internal。
4.2 构建一个真实可用的Demo:三文件最小闭环
我为你准备了一个真正能跑通的Demo,只需三个文件:
1. demo.docx:用Word新建一个空白文档,输入“OnlyOffice 9.4 Demo测试”,保存为.docx格式;
2. callback.php(模拟你的业务系统接收保存回调):
<?php // 保存到本地,仅作演示 file_put_contents('/tmp/saved_' . date('YmdHis') . '.docx', file_get_contents('php://input')); http_response_code(200); echo '{"error":0}'; ?>放在Nginx的/var/www/html/下,确保可通过http://your-ip/callback.php访问;
3. demo.html(修改后的index.html):
<!DOCTYPE html> <html> <head><title>OnlyOffice 9.4 Demo</title></head> <body> <div id="placeholder" style="width:100%;height:800px;"></div> <script type="text/javascript" src="https://onlyoffice.github.io/sdkjs/latest/web-apps/apps/api/documents/api.js"></script> <script> var docEditor = new DocsAPI.DocEditor("placeholder", { "document": { "fileType": "docx", "key": "demo-key-" + Date.now(), // 时间戳保证唯一 "title": "demo.docx", "url": "http://192.168.1.100/demo.docx" // 改成你的宿主机IP }, "editorConfig": { "mode": "edit", "callbackUrl": "http://192.168.1.100/callback.php", "token": { "inbox": "my_secret_inbox_token" } } }); </script> </body> </html>把这三个文件放到Nginx的/var/www/html/下,访问http://your-ip/demo.html。此时流程是:浏览器加载SDK → SDK向DS发起编辑请求 → DS下载demo.docx→ 渲染编辑器 → 你修改内容 → 点保存 → DS POST数据到callback.php→ 你看到/tmp/下生成新文件。
4.3 插件开发初探:在Demo中注入一个“一键插入当前时间”的按钮
OnlyOffice 9.4插件开发的核心是plugin.js,它必须放在/var/www/onlyoffice/Data/plugins/下,并在local.json中声明:
# 创建插件目录 mkdir -p /opt/onlyoffice/Data/plugins/time-plugin # 编写插件 cat > /opt/onlyoffice/Data/plugins/time-plugin/plugin.js << 'EOF' (function (window, undefined) { var pluginDef = { name: "time-plugin", title: "插入时间", autoShow: false, init: function () { this.createButton(); }, createButton: function () { var oButton = new Asc.plugin.Button({ id: "btnInsertTime", title: "插入当前时间", hint: "插入YYYY-MM-DD HH:MM:SS", enable: true, image: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>' }); this.addButton(oButton); }, button: function (e) { if (e.id === "btnInsertTime") { var oDocument = Api.GetDocument(); var oParagraph = Api.CreateParagraph(); oParagraph.AddText(new Date().toLocaleString()); oDocument.InsertContent([oParagraph]); } } }; window.Asc.plugin = window.Asc.plugin || {}; window.Asc.plugin.executeMethod = function (method, args) { if (method === "onPluginLoad") { pluginDef.init(); } }; })(window, undefined); EOF然后在/etc/onlyoffice/documentserver/local.json的plugins节点添加:
"plugins": { "enable": true, "path": "/var/www/onlyoffice/Data/plugins" }重启DS容器,打开demo.html,编辑器右上角会出现“插入时间”按钮。点击即在光标处插入当前时间。
实操心得:插件JS里不能用
console.log,日志全在/var/log/onlyoffice/documentserver/out.log里;Api.GetDocument()返回的是OnlyOffice内部文档对象,不是DOM;图标必须是SVG字符串,不能引用外部URL。
4.4 日志分析与性能调优:从log看懂DS的每一秒
OnlyOffice 9.4的日志分散在三个文件:
/var/log/onlyoffice/documentserver/out.log:Node.js主进程日志,记录HTTP请求、WebSocket连接、插件加载;/var/log/onlyoffice/documentserver/converter/out.log:libreoffice转换日志,记录DOCX转PDF的每一步;/var/log/onlyoffice/documentserver/err.log:错误汇总,所有ERROR级别的消息。
例如,当你看到out.log里有:
[2024-03-15 10:22:34.123] [DEBUG] nodeJS - Sending command: {"c":"conv","key":"abc123","url":"http://192.168.1.100/demo.docx"}说明DS已收到转换请求;紧接着converter/out.log里出现:
INFO 2024-03-15 10:22:35,123 [Thread-1] com.onlyoffice.converter.Converter - Converting /tmp/conv/abc123.docx -> /tmp/conv/abc123.pdf说明libreoffice已接手。如果卡在这里超过30秒,大概率是字体缺失或内存不足。
性能调优关键参数在local.json:
"services": { "CoAuthoring": { "converter": { "maxDownloadBytes": 104857600, // 最大下载文件100MB "maxUploadBytes": 104857600, // 最大上传100MB "libreoffice": { "maxMemory": 4294967296 // libreoffice最大内存4GB,防止OOM } } } }5. 常见问题与排查技巧实录:那些官网文档不会告诉你的坑
5.1 问题速查表:高频故障与一招解
| 现象 | 可能原因 | 排查命令 | 解决方案 |
|---|---|---|---|
访问/sample白屏,Console报Uncaught ReferenceError: DocsAPI is not defined | api.js未加载成功 | curl -I https://onlyoffice.github.io/sdkjs/latest/web-apps/apps/api/documents/api.js | 换国内CDN,如https://cdn.jsdelivr.net/npm/onlyoffice-sdk@1.0.0/web-apps/apps/api/documents/api.js |
新建文档后显示“正在连接服务器…”,Network里CommandService.ashx状态为(pending) | WebSocket被防火墙拦截 | telnet your-ip 3000 | 在Nginx配置中添加proxy_read_timeout 3600;并开放3000端口 |
| PDF导出后中文乱码,显示为方块 | 字体未被libreoffice识别 | docker exec onlyoffice-ds libreoffice --headless --convert-to pdf /tmp/test.docx | 进入容器执行fc-list | grep "Source",确认字体存在后,重启libreoffice:docker exec onlyoffice-ds pkill -f libreoffice |
插件按钮显示但点击无反应,out.log无日志 | 插件JS语法错误 | docker exec onlyoffice-ds node -c "console.log(require('/var/www/onlyoffice/Data/plugins/time-plugin/plugin.js'))" | 用node -c验证JS语法,修复<svg>标签闭合错误 |
docker logs onlyoffice-ds显示FATAL: password authentication failed for user "onlyoffice" | PostgreSQL密码错误(仅CS场景) | docker exec -it onlyoffice-cs cat /etc/onlyoffice/communityserver/local.json | grep password | 修改local.json中services.PostgreSQL.password,与PostgreSQL容器密码一致 |
5.2 Docker部署专属避坑指南
坑1:SELinux导致挂载失败
CentOS 7/8默认开启SELinux,-v /opt/onlyoffice/Data:/var/www/onlyoffice/Data会报Permission denied。解决方案:chcon -Rt svirt_sandbox_file_t /opt/onlyoffice/Data或临时禁用setenforce 0(生产环境不推荐)。坑2:Docker DNS污染导致GitHub SDK加载慢
api.js从GitHub加载,国内DNS常解析到海外IP。在/etc/docker/daemon.json中添加:{ "dns": ["114.114.114.114", "8.8.8.8"] }然后
systemctl restart docker。坑3:容器时间与宿主机不同步
OnlyOffice 9.4的JWT token校验依赖时间,误差超5分钟会报token expired。启动容器时加参数:docker run -d --name onlyoffice-ds --privileged -v /etc/localtime:/etc/localtime:ro ...
5.3 开发调试黄金组合:Chrome DevTools + DS日志 + curl三联
调试一个编辑请求的完整链路:
- Chrome Network:过滤
/coauthoring/,看POST /coauthoring/CommandService.ashx的Request Payload,确认c:"open"和key字段正确; - DS out.log:搜索该
key,看是否出现Open document with key: abc123; - curl模拟请求:
如果返回curl -X POST http://localhost:3000/coauthoring/CommandService.ashx \ -H "Content-Type: application/json" \ -d '{"c":"open","key":"test123","url":"http://192.168.1.100/demo.docx"}'{"error":0},说明DS服务正常;如果返回{"error":7},是token错误;{"error":10}是文件下载失败。
这套组合拳能精准定位问题发生在前端、网络、还是DS内部。
5.4 安全加固必须做的五件事
OnlyOffice 9.4默认配置不适用于生产环境,上线前必须:
- 禁用默认管理员接口:
/healthcheck和/metrics暴露服务状态,Nginx中屏蔽:location /healthcheck { return 403; } location /metrics { return 403; } - 强制HTTPS:在Nginx中添加
return 301 https://$host$request_uri;,并配置Let's Encrypt证书; - 限制上传文件类型:在
local.json中设置:"upload": { "extensions": ["docx", "xlsx", "pptx", "pdf"] } - 关闭调试模式:
local.json中"debug": false,避免日志泄露敏感路径; - 定期清理缓存:写个cron脚本每天清理
/opt/onlyoffice/Data/cache/下7天前的文件,防止磁盘爆满。
5.5 版本升级平滑过渡方案
OnlyOffice 9.4升级到9.5不能直接docker pull && docker restart,因为:
- 数据库结构变更(CS场景);
local.json新增字段(如services.CoAuthoring.spellchecker.enabled);- 插件API有Breaking Change(如
Asc.plugin.info返回字段调整)。
我的升级流程:
- 备份
/opt/onlyoffice/Data/全量目录; - 拉取新镜像
onlyoffice/documentserver:9.5.0; - 启动新容器但不挂载
Data卷,进入容器执行/usr/bin/documentserver-generate-config.sh生成新版local.json模板; - 将旧
local.json中的自定义字段(token、路径、插件)逐个迁移到新模板; - 用新配置启动容器,验证
/sample和核心功能; - 逐步切换业务流量,观察日志无
WARN级别以上错误后,完成切换。
整个过程约45分钟,零停机。
我在实际项目中用这套方法完成了6次大版本升级,最惊险的一次是9.3→9.4,客户要求凌晨2点操作,我提前3天在测试环境跑通全流程,上线时只花了22分钟。那种看着所有文档无缝切换到新版本,编辑、评论、导出全部正常的感觉,比喝十杯咖啡都提神。如果你现在正对着白屏的/sample页面发愁,别急着重装,回到
