Docker部署ONLYOFFICE文档服务:Nginx反代与HTTPS配置全攻略
2026/9/17 22:10:48 网站建设 项目流程

1. 为什么选Docker部署ONLYOFFICE,而不是裸机装

1.1 官方镜像到底装了什么,一个容器等于一整套服务

我第一次接触ONLYOFFICE时,下意识以为它和LibreOffice差不多,装个依赖、跑个服务、配置一下就能用。真正上手才发现,ONLYOFFICE Document Server是一整套文档处理服务,里面有文档转换引擎、在线编辑回调、协同编辑会话管理,背后还依赖PostgreSQL、RabbitMQ、Redis这些组件。如果走传统裸机安装,光是把这些依赖版本对齐、配置不冲突、开机自启全搞定,够你折腾一整天。

用Docker部署就是另一回事了。官方维护的onlyoffice/documentserver镜像把所有运行时都打包好了,容器内部自带了Nginx、PostgreSQL、RabbitMQ、Redis和文档服务本体。你只需要一条docker run命令,拉起来就能跑。这背后的逻辑说得直白点:官方替你解决了“组件之间怎么配合”的问题,你只需要关心“我该把哪些数据持久化、端口怎么映射、证书放哪里”。

我之所以坚持用Docker,还有一个很实际的原因——升级和回滚。ONLYOFFICE社区版更新频率不低,裸机升级要备份数据、停服务、替换包、重启一堆组件,中间任何一个环节出错,在线编辑功能就挂了。容器方式只需要换镜像Tag再重建容器,数据卷不动,升级风险小很多。万一新版本有问题,切回旧镜像,一条命令恢复原样。

1.2 容器版本和裸机版本怎么选

先看一张我自己整理的对比表,方便你判断自己场景适合哪种方式:

对比项Docker部署裸机/虚拟机部署
部署耗时10分钟左右(取决于拉镜像速度)至少半天,踩坑可能要一两天
组件依赖容器内置,自动管理需手动安装Nginx/PG/RabbitMQ/Redis
升级回滚改Tag重建容器,分钟级完成手动备份+替换包,链路长
资源占用镜像分层,实际内存占用略高相对更节约,但差异不大
与宿主耦合低,日志和数据目录挂载出来后很清晰高,环境变动可能影响服务
适合场景中小团队、快速上线、需要频繁升级对资源敏感、已有完整运维体系的大厂

如果你的服务器内存小于4GB,我建议慎重考虑ONLYOFFICE。这个服务本身很吃内存,容器跑起来基线就要1.5GB到2GB左右,如果再塞进Java后端、MySQL等业务服务,很容易触发OOM。文档转换和大文档并发编辑时内存还会继续涨。内存再少,哪怕是部署成功了,在线编辑体验也会卡到怀疑人生。

我在公司内部部署时,给这台服务单独分配的配置是4核8GB,同时跑ONLYOFFICE容器和Nginx反代,实测连续10个人同时在线编辑、频繁保存修改,内存使用率稳定在70%以下,没有发生过OOM。

2. 部署前的环境评估与关键参数准备

2.1 域名和证书方案:免费证书、自签证书、商业证书怎么选

ONLYOFFICE的HTTPS方案有个特点:它不是“部署完了能打开网页”就行,还要考虑编辑器保存时服务端之间的回调。你的业务系统(比如Java后端)会通过HTTPS回调ONLYOFFICE服务,如果证书不被系统信任,回调就会失败,表现症状就是“编辑器打不开”、“保存报错”、“一直加载中”。

所以证书选型很关键。按我实际经验,优先级如下:

第一选择:Let's Encrypt免费证书。如果你有公网域名,直接申请Let's Encrypt,90天有效期,配合certbot自动续期,经过实际验证最省心、兼容性最好,浏览器和服务端两边都认。

第二选择:自签CA证书并加入信任链。如果你在内网环境没有公网域名,也没法通往外网,那只能自签。但要注意,自签证书不能只签一张,最好用自建CA签发服务器证书,然后让所有调用ONLYOFFICE的客户端和服务端都信任这个CA。后面我会细讲这个操作。

第三选择:商业证书。适合对证书链完整性和品牌展示有要求的生产环境,比如要交付给外部客户使用。商业证书签发流程和Let's Encrypt类似,只是要花钱买。

不建议直接裸奔用HTTP。一旦你的业务页面是HTTPS,浏览器会拦截对HTTP资源的请求,ONLYOFFICE编辑器根本加载不出来。所以HTTPS不是可选项,是必选项。

2.2 服务器、防火墙与Docker环境准备

在动手前,先把这些准备工作做完,省得后面踩坑:

  1. 开放端口:至少放行80443端口。ONLYOFFICE文档服务走的是80端口,Nginx反代对外提供443。如果你在内网,需要在防火墙上放行;如果在云服务器,还要去安全组里加规则。我实际遇到过一个情况:服务器本地curl没问题,外部浏览器就是连不上,排查了一圈发现是云安全组忘了放行443。

  2. 安装Docker和Docker Compose:建议直接用官方安装脚本装Docker,版本不要太老。Docker Compose看是否单独需要,如果用docker compose插件形式,直接就能用。国内拉镜像慢的,提前在/etc/docker/daemon.json里配置镜像加速地址,配置完重启Docker再拉镜像。

  3. 确认系统时区:ONLYOFFICE的日志时间要是差了8小时,排查问题时会很痛苦。建议把宿主机和容器都设置成Asia/Shanghai。容器时间可以通过环境变量TZ指定。

  4. 检查内存和Swap:保险起见,给这台服务器至少要4GB可用内存。如果内存紧张,可以加2GB Swap兜底,但Swap不能解决所有问题,长时间高负载应用别依赖Swap。

2.3 数据卷挂载和JWT参数,这些配置要提前想明白

ONLYOFFICE容器把数据分成几个目录,分别是文档数据、数据库、日志、配置。强烈建议把它们全部持久化到宿主机目录,否则容器一删数据全没了。我在生产环境中用的挂载规则如下:

容器内路径宿主机路径存什么
/var/www/onlyoffice/Data/opt/onlyoffice/data文档、证书、字体等用户数据
/var/log/onlyoffice/opt/onlyoffice/logs服务日志
/var/lib/onlyoffice/opt/onlyoffice/lib扩展和缓存
/var/lib/postgresql/opt/onlyoffice/dbPostgreSQL数据文件

挂载目录的权限要注意。容器里的进程用户不是root,宿主机目录如果是root用户的默认权限,容器可能写不进去。我在第一次部署时就直接建目录、默认权限,结果PostgreSQL初始化失败,容器反复重启。后来把目录属主改成root还不够,用chmod -R 777才跑起来。不推荐777放在公网服务器上,但内网场景可以接受;更稳妥的做法是找到容器里运行用户的UID,然后把宿主机目录属主设置成那个UID。

还有JWT参数。ONLYOFFICE从7.x版本开始默认启用JWT签名,编辑器向文档服务发起请求时都要带token,防止被伪造。你的集成方(比如Java后端、NextCloud、自定义前端)如果没配置同一个JWT_SECRET,会出现“文档密钥无效”之类的报错。我建议自己生成一个超过32位的随机字符串,保存好,后面所有地方都用这个。

3. 核心实操:Docker部署ONLYOFFICE文档服务

3.1 拉取镜像并启动容器,完整命令和Compose配置

先拉镜像。注意不要用latest,生产环境最好锁定一个大版本Tag,比如7.5.0,等测试无误后再升级。

docker pull onlyoffice/documentserver:7.5.0

启动方式有两种。不需要编排的服务,直接docker run最快:

docker run -i -t -d -p 80:80 \ --restart=always \ --name onlyoffice \ -v /opt/onlyoffice/data:/var/www/onlyoffice/Data \ -v /opt/onlyoffice/logs:/var/log/onlyoffice \ -v /opt/onlyoffice/lib:/var/lib/onlyoffice \ -v /opt/onlyoffice/db:/var/lib/postgresql \ -e "JWT_ENABLED=true" \ -e "JWT_SECRET=your_strong_secret_here_at_least_32_chars" \ -e "TZ=Asia/Shanghai" \ onlyoffice/documentserver:7.5.0

如果你更习惯Compose管理,可以这样写:

version: '3' services: onlyoffice: image: onlyoffice/documentserver:7.5.0 container_name: onlyoffice restart: always ports: - "80:80" environment: - JWT_ENABLED=true - JWT_SECRET=your_strong_secret_here_at_least_32_chars - TZ=Asia/Shanghai volumes: - /opt/onlyoffice/data:/var/www/onlyoffice/Data - /opt/onlyoffice/logs:/var/log/onlyoffice - /opt/onlyoffice/lib:/var/lib/onlyoffice - /opt/onlyoffice/db:/var/lib/postgresql

这里解释一下为什么映射的是80:80。ONLYOFFICE容器内部自带了一个Nginx,监听80端口。它负责把请求分发到文档服务的各个内部组件。外部想直接用HTTPS访问,不能在容器内把443直接映射出去,因为容器内没有配置证书。正确做法是让容器继续监听80,在外层用Nginx(宿主机Nginx或独立Nginx容器)接收443流量,再反代到容器80端口。这也是官方推荐的做法。

启动后先看日志,确认有没有报错:

docker logs -f onlyoffice

观察输出里有没有“successful”或者报PostgreSQL、NetCore服务启动失败的日志。首次启动要初始化数据库,可能需要一分钟左右,别急着下结论。

3.2 验证容器是否正常:healthcheck和欢迎页

容器启动完成后,先在本机验证一下。

curl -I http://localhost/healthcheck

正常情况下会返回HTTP 200,响应体是字符串true。这说明文档服务核心进程和数据库连接都是好的。

再打开http://你的服务器IP/welcome/,能看到ONLYOFFICE的欢迎页面。这个页面本身不能编辑文档,但是能验证Nginx路由是否正常。真正测试在线编辑,需要通过集成的业务系统发起一个编辑请求。

我在这一步遇到过一个问题:healthcheck返回200,但欢迎页打不开。后来发现是容器内的Nginx配置和Data目录没挂载对,部分静态资源读取失败。这种问题要看容器日志才能发现,所以我会反复强调:任何异常先看docker logs

3.3 踩坑记录:为什么容器起来了,HTTPS还是访问不了

很多新手在这里会疑惑:ONLYOFFICE容器已经监听80了,浏览器通过http://ip也能打开,那HTTPS怎么弄?直接在Docker映射443端口行不行?

先说结论:不行。

容器内部的Nginx只监听80,而且没有任何证书配置。即使你把宿主机的443映射到容器的80,也不是HTTPS。浏览器访问https://ip时,TLS握手发生在容器外的Nginx(或负载均衡器)上,不是容器内的Nginx。所以一旦你的业务站点升级成了HTTPS,浏览器加载http://onlyoffice资源时就会被混合内容策略拦截,编辑器白屏、加载不到脚本,就是这一步导致的。

接下来要做的事情就清晰了:在宿主机上装一个Nginx,承担TLS终止和反向代理的职责。容器继续留在80端口做人肉转发,最省心。

4. 打通HTTPS访问链路:Nginx反向代理配置详解

4.1 宿主机Nginx还是Nginx容器,怎么选

我推荐直接在宿主机装Nginx,不建议再开一个Nginx容器。理由有三点:

  1. 少一个容器就少一层网络通信和资源占用。
  2. 证书续期的时候Skyler通过宿主机文件直接挂载进去,比docker cp进容器再reload简单得多。
  3. 排错链路更短:客户端 -> 宿主机Nginx -> Docker容器,openSSL和curl测试都很方便。

除非你有一整套基于容器的统一运维平台,否则宿主机Nginx是中小团队最优解。

Nginx安装方式不多说,Ubuntu/Debian用apt install nginx,CentOS用yum install nginx。装完把默认站点禁用,新建一个ONLYOFFICE专属配置。

4.2 申请Let's Encrypt证书并配置Nginx

我的服务器是Ubuntu,直接装certbot:

apt install certbot python3-certbot-nginx -y

如果ONLYOFFICE已经在80端口跑起来了,先确保有一个域名解析到这台服务器IP,然后执行:

certbot --nginx -d onlyoffice.example.com

certbot会自动修改Nginx配置并配置好证书路径。如果你不想让它自动改Nginx配置,也可以用WebRoot方式只签发证书,手动写Nginx配置。我更推荐手动方式,因为ONLYOFFICE有一些特殊的代理参数,certbot自动生成的模板不一定合适。

手动配置的核心Nginx站点文件如下:

server { listen 443 ssl http2; server_name onlyoffice.example.com; ssl_certificate /etc/letsencrypt/live/onlyoffice.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/onlyoffice.example.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; # 上传大小限制,建议设置大一些,否则大文档上传会413 client_max_body_size 100m; # ONLYOFFICE在线编辑是长连接,读超时和发送超时都要放长 proxy_read_timeout 3600s; proxy_send_timeout 3600s; location / { proxy_pass http://127.0.0.1:80; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } } server { listen 80; server_name onlyoffice.example.com; return 301 https://$host$request_uri; }

保存后测试配置并重载Nginx:

nginx -t systemctl reload nginx

然后访问https://onlyoffice.example.com/welcome/,浏览器不再报证书错误,整个链路就算打通了。

注意proxy_set_header X-Forwarded-Proto $scheme这一行很关键。ONLYOFFICE文档服务会通过这个头判断请求是HTTP还是HTTPS,然后在回调URL、资源引用地址里生成对应的协议。如果漏掉这个头,即使你浏览器通过HTTPS访问,文档服务生成的内部URL仍可能是HTTP,编辑器照样加载不全。

4.3 WebSocket和代理缓冲这些参数为什么不能省

ONLYOFFICE在线编辑过程中,协同编辑和文档变化的推送依赖WebSocket。Nginx反代WebSocket需要特殊处理,就是配置里那两行:

proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";

没有这两行,你打开编辑器能加载文档,但多人协同编辑时,别人输入的字符不会实时同步,还会出现“连接已断开”的提示。这个问题比较隐蔽,不排查很难发现。

还有代理缓冲。Nginx默认会缓冲后端响应,ONLYOFFICE有些实时交互接口需要即时返回数据,如果缓冲导致延迟过大,编辑器会表现得很“卡顿”。我通常会在location里加上:

proxy_buffering off; proxy_cache off;

实测下来,这两个配置对首屏加载速度和保存响应体感有提升。

4.4 证书自动续期,避免90天后访问突然挂掉

Let's Encrypt证书有效期只有90天,必须配置自动续期。certbot提供了一个--renew-hook参数,在续期成功后重载Nginx,让新证书生效。

certbot renew --renew-hook "systemctl reload nginx"

用crontab每两天执行一次检查:

0 3 */2 * * /usr/bin/certbot renew --renew-hook "systemctl reload nginx" >> /var/log/letsencrypt/renew.log 2>&1

续期操作本身不会中断ONLYOFFICE服务,因为只是把证书文件替换掉,Nginx reload是平滑重载,不丢连接。

5. 常见问题与排查技巧实录

5.1 编辑器一直加载/文档服务返回错误,先怀疑回调链路

在线编辑架构里,你的业务服务器和ONLYOFFICE文档服务器之间是“服务端到服务端”的通信。最常见的一个坑:业务服务器访问ONLYOFFICE时,用的还是自签证书或内网IP,导致TLS校验失败。

我处理过一个典型case:业务站点是https://oa.example.com,ONLYOFFICE部署在内网http://192.168.1.100,业务页面能正常打开编辑器框架,但一发起编辑请求就报“文档服务返回错误”。

查下来发现,业务后端回调ONLYOFFICE的地址是http,但浏览器里的混合内容拦截了该HTTP地址。解决办法:给ONLYOFFICE配上HTTPS域名,业务后端回调地址改为https://onlyoffice.example.com,两边全是HTTPS,问题立刻消失。

处理这种问题,我习惯分三步排查:

  1. 在服务器上用curl -I http://localhost/healthcheck确认文档服务存活。
  2. curl -I https://onlyoffice.example.com/healthcheck确认外部HTTPS链路正常。
  3. curl -vk https://onlyoffice.example.com检查证书链是否完整,结合-k只是跳过验证看返回。

如果第二步和第三步失败,问题出在Nginx或证书;如果都通过,问题多半出在业务系统的回调地址或JWT配置。

5.2 浏览器内网IP访问HTTPS,证书警告无法消除

这个问题的根源是证书和访问地址不匹配。Let's Encrypt证书只能签域名,不能签IP地址(除非是公有IP且有特殊验证)。你在内网用https://192.168.1.100访问,浏览器会报“证书名称不匹配”,即使证书部署正确也一样。

解决办法有两个:

一是内网DNS加域名解析,把onlyoffice.example.com解析到内网IP,然后用域名访问,信任Let's Encrypt根证书,提示自然消失。强烈推荐这种方式。

二是自签CA。如果没有内网DNS,就自己建CA,签发一个带内网IP或内网域名的证书,再把这个CA导入所有客户端的信任列表。这套操作对服务器端也要做一次,因为服务端之间调用的时候,也需要信任这个自签CA。

5.3 Java后端调用ONLYOFFICE时证书校验不过,怎么解决

Java程序默认信任JDK的cacerts证书库。如果ONLYOFFICE用的是自签证书,Java会报PKIX path building failed

解决思路有两个:

  • 把自签CA证书导入Java的cacerts证书库:keytool -import -trustcacerts -alias onlyoffice-ca -file ca.crt -keystore cacerts
  • 或者在后端代码里跳过SSL验证。这个方法测试环境应急可以,生产环境一定要用方案一,跳过验证等于把安全守门员撤掉了,风险太高。

5.4 在线编辑保存报错,看ONLYOFFICE容器日志找真相

保存失败这个问题,经常被表象带偏。有一次用户反馈总是在编辑后点击保存时报错,但有时能保存成功。我一开始怀疑是内存不足,看了系统指标很正常。后来进容器看日志:

docker logs --tail 200 onlyoffice

发现大量RabbitMQ connection is not open之类的连接错误。查了一下,容器里的RabbitMQ和ONLYOFFICE服务之间有内部网络通信,由于我宿主机做了端口映射冲突,导致RabbitMQ初始化异常。排查后调整端口映射,问题解决。

所以遇到保存失败、连接断开这类问题,第一件事永远是看容器日志,别凭感觉改配置。ONLYOFFICE日志文件在挂载的/opt/onlyoffice/logs目录下,结合时间点查看docserviceconverter相关日志最有用。

5.5 容器反复重启,多半是数据卷权限或内存不足

ONLYOFFICE容器启动失败、反复重启,最常见的原因就是挂载目录权限不对。容器里的PostgreSQL进程以postgres用户身份跑,如果你宿主机挂载的目录权限不允许它写,数据库初始化就会失败。

这时候用docker logs能看到清晰的权限报错。解决办法:先停容器,把数据库目录的属主改成容器内PostgreSQL的UID。查找UID用这条命令:

docker run --rm onlyoffice/documentserver:7.5.0 id postgres

一般得到的UID是999,然后把宿主机数据库目录属主改成这个:

chown -R 999:999 /opt/onlyoffice/db

改完再启动容器,基本就好了。

还有内存不足的问题。ONLYOFFICE社区版对内存管理不吝啬,单文档转换进程可能吃掉几百MB。系统内存不够时会触发内存回收甚至OOM Killer杀掉容器进程,表现就是容器重启。最简单有效的调优方案是把文档转换并发数上限降低,修改容器内配置文件/etc/onlyoffice/documentserver/local.json里的converter\.converter\.concurrency,调成2或4,降低峰值内存压力。

5.6 修改local.json配置后不生效,记得重建容器

ONLYOFFICE的配置修改后,需要在容器内重启文档服务相关进程才会生效。单纯改宿主机目录里的文件不会立刻加载。

常见的做法:

docker exec -it onlyoffice supervisorctl restart all

如果你的配置始终不生效,可以检查一下挂载映射是否正确。我曾经因为把/opt/onlyoffice/lib挂载到了容器里,但local.json实际路径在/etc/onlyoffice,所以改挂载目录里的文件根本没用。后来把/etc/onlyoffice单独挂载出来,才实现了配置持久化。

注意:ONLYOFFICE镜像里的/etc/onlyoffice目录在多版本镜像里路径是相对稳定的,但官方升级有可能会改默认配置。生产环境我建议都用local.json覆盖层,不要直接改全局配置文件,升级时冲突少。

6. 在线编辑集成时,几个容易忽略的隐蔽细节

6.1 业务系统是HTTPS,ONLYOFFICE也必须是HTTPS

很多团队部署ONLYOFFICE时,业务系统已经跑在HTTPS。浏览器加载在线编辑器时,嵌入页面的方式通常是iframe或JS调用。如果父页面是HTTPS,iframe里的源是HTTP,浏览器会直接拦截,白屏问题就是这么来的。

所以集成ONLYOFFICE前,先确认自己的业务页面协议和ONLYOFFICE访问协议保持一致。HTTPS页面就配HTTPS的ONLYOFFICE,这在架构设计阶段就要定下来,后期再改证书和回调地址很麻烦。

6.2 JWT密钥不一致,编辑器报“invalid token”

ONLYOFFICE 7.x之后,文档服务默认开启JWT。如果你在容器启动时只设置了JWT_ENABLED=true,没有设置固定的JWT_SECRET,容器会随机生成一个密钥,你业务系统那边根本不知道这个密钥,所有来自集成方的请求都会被判定为无效。

启动时必须手动指定:

-e "JWT_SECRET=your_strong_secret_here"

然后把这个密钥同步到业务系统的配置里。Java集成时常见的是在初始化连接器时传入jwtSecret参数。两边不一致,就会出现一个很经典的报错:JWT verification failedInvalid token

网上有些旧教程让你把JWT_ENABLED改成false来绕过。这可以做,但我不建议在生产环境这么做,因为它会让未授权的人绕过校验直接调用文档服务接口,等于把文档编辑入口裸奔在公网上。安全无小事,多花一分钟配置密钥,省的是后面出事的麻烦。

6.3 服务端之间回调地址不能写localhost

这个坑特别隐蔽。如果你在服务器上同时部署了ONLYOFFICE容器和业务系统容器,并在业务系统里把ONLYOFFICE地址配置成了http://localhosthttp://127.0.0.1,看起来能通,但浏览器端实际加载编辑器时,你的用户浏览器解析不到这个localhost。

正确的做法是填外部可访问的地址,比如https://onlyoffice.example.com。不仅用户浏览器能访问,业务服务器也能访问。这样才能保证前端编辑和后端回调走同一条链路。

6.4 使用强制HTTPS跳转后,ONLYOFFICE的WebSocket也要跟着走HTTPS

如果你在Nginx里配置了80强制跳转443,ONLYOFFICE的WebSocket连接也必须走wss://。Nginx配置里带上Upgrade头即可,大多数情况下它会自动跟随X-Forwarded-Proto生成wss。如果发现编辑器能打开但实时协同失效,用开发者工具看WebSocket连接状态,如果显示ws://,多半是Nginx头配置没生效。

6.5 文档转换和预览为什么慢,先检查字体缓存

ONLYOFFICE转换文档依赖中文字体,如果容器里没有中文字体,转换出的PDF会出现乱码,甚至转换失败。部署时建议把宿主机常见字体挂载进容器,或者复制到Data目录下的字体目录。我在生产环境做法是:

cp -r /usr/share/fonts/truetype/* /opt/onlyoffice/data/fonts/

然后重启容器。这个操作很小的,但对中文文档体验提升非常明显。

最后再分享一个小技巧

在实际部署ONLYOFFICE的时候,我习惯把所有配置和挂载统一整理成一个Shell脚本或Compose文件,放在/opt/onlyoffice目录里。这样不管是审计、迁移还是重新部署,一条命令就能恢复整套服务。

容器部署最大的价值在于“可复现”,如果你只是手动敲命令配好就跑,那这套环境在三个月后可能连你自己都说不清楚是怎么搭出来的。把所有操作变成代码和配置,才是Docker真正改变运维方式的地方。ONLYOFFICE本身很成熟,配合上HTTPS访问,更像是一个正规生产系统的样子,这套方案我在多个项目里实际跑过,稳定可靠,希望这篇文章能让你少走几个我已经踩过的坑。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询