OnlyOffice 9.4文档服务部署与Document Server深度解析

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 ServerDS和Community ServerCS是两个独立进程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.0communityserver:9.4.0 自建PostgreSQL 14 Redis 7全部用Docker Compose编排。这样做的好处是每个组件版本可控、日志隔离清晰、扩容缩容独立、安全策略可精细化比如DS只暴露80/443CS只对内网开放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调用插件APIL2 Nginx层不只是反向代理它承担了静态资源缓存/static、WebSocket连接维持/coauthoring/CommandService.ashx、以及关键的/cache路径重写把/cache/files/xxx.docx映射到/var/www/onlyoffice/Data/cache/files/xxx.docxL3 Document Server应用层基于Node.js的Express服务主进程监听3000端口内部通信Nginx将其代理到80端口对外提供服务核心模块包括DocEditor编辑器主控、FileConverter格式转换、SpellChecker拼写检查L4 系统依赖层libreoffice文档转换引擎、ffmpeg视频预览、ghostscriptPDF处理、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 ServerCS是完整的SaaS化后台带用户管理、存储集成、API网关但它会引入MySQL、Redis、Elasticsearch等额外组件把问题复杂度指数级放大。而Document ServerDS是纯粹的文档处理引擎它自带一个轻量级的sampledemo路径是http://your-ip/sample/index.html这个页面完全静态不调用任何后端API只通过iframe srchttp://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。我实测的最低可行配置是CPU4核推荐Intel Xeon E3或AMD Ryzen 5ARM架构需额外编译libreoffice不建议新手内存8GBDS自身占3GBlibreoffice单实例峰值5GB留1GB给系统磁盘SSD至少20GB空闲/var/www/onlyoffice/Data/cache/会快速膨胀一个100页PPT转PDF生成的临时文件超200MB操作系统Ubuntu 22.04 LTS官方唯一长期支持的发行版内核≥5.15低版本存在inotify事件丢失导致文件监控失效的问题Docker24.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.jsondocker 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:styleRegular注意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/sampleclone下来发现跑不起来——因为那是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 typetext/javascript srchttps://onlyoffice.github.io/sdkjs/latest/web-apps/apps/api/documents/api.js/script !-- 初始化编辑器 -- div idplaceholder/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 headtitleOnlyOffice 9.4 Demo/title/head body div idplaceholder stylewidth:100%;height:800px;/div script typetext/javascript srchttps://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 xmlnshttp://www.w3.org/2000/svg width24 height24 viewBox0 0 24 24path dM12 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.logNode.js主进程日志记录HTTP请求、WebSocket连接、插件加载/var/log/onlyoffice/documentserver/converter/out.loglibreoffice转换日志记录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.jsonservices: { CoAuthoring: { converter: { maxDownloadBytes: 104857600, // 最大下载文件100MB maxUploadBytes: 104857600, // 最大上传100MB libreoffice: { maxMemory: 4294967296 // libreoffice最大内存4GB防止OOM } } } }5. 常见问题与排查技巧实录那些官网文档不会告诉你的坑5.1 问题速查表高频故障与一招解现象可能原因排查命令解决方案访问/sample白屏Console报Uncaught ReferenceError: DocsAPI is not definedapi.js未加载成功curl -I https://onlyoffice.github.io/sdkjs/latest/web-apps/apps/api/documents/api.js换国内CDN如https://cdn.jsdelivr.net/npm/onlyoffice-sdk1.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确认字体存在后重启libreofficedocker 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 onlyofficePostgreSQL密码错误仅CS场景docker exec -it onlyoffice-cs cat /etc/onlyoffice/communityserver/local.json | grep password修改local.json中services.PostgreSQL.password与PostgreSQL容器密码一致5.2 Docker部署专属避坑指南坑1SELinux导致挂载失败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生产环境不推荐。坑2Docker 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: abc123curl模拟请求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;并配置Lets 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页面发愁别急着重装回到