1. 部署方案选择
OnlyOffice Docs 有三种主要的部署方式,选择哪种取决于你的规模和运维能力:
方案一:Docker 单容器(快速验证)
适合开发测试和小规模使用(并发 20 以下),所有组件打包在单个容器内,一行命令启动,但灵活性差,无法独立扩展某个组件。
方案二:Docker Compose 多服务(推荐,本文重点)
将 Document Server、PostgreSQL、RabbitMQ、Redis 分别跑在独立容器中,通过 Docker Compose 编排。配置灵活、组件可独立重启、便于数据卷管理,适合生产环境的中小规模部署(并发 20–200)。
方案三:Kubernetes(大规模)
适合需要高可用和水平扩展的场景(并发 200 以上)。官方提供 Helm Chart,但配置复杂度显著上升。本文不展开 K8s 部署,第四篇聚焦 Docker Compose 方案,K8s 方案留待后续专题。
本文以**方案二(Docker Compose)**为核心,这也是绝大多数生产环境的实际选择。
2. 环境准备与资源规划
2.1 硬件资源建议
OnlyOffice 是一个重型服务,不要低估资源需求。官方建议和实际经验汇总如下:
| 并发连接数 | CPU | 内存 | 磁盘 | 网络带宽 |
|---|---|---|---|---|
| 测试 / ≤10 | 2 核 | 4 GB | 40 GB SSD | 10 Mbps |
| 小型生产 / 10–50 | 4 核 | 8 GB | 100 GB SSD | 50 Mbps |
| 中型生产 / 50–100 | 8 核 | 16 GB | 200 GB SSD | 100 Mbps |
| 大型生产 / 100–200 | 16 核 | 32 GB | 500 GB SSD | 200 Mbps |
几点说明:
- "并发连接数"指同时在编辑器中活跃的用户数,不是注册用户数
- 磁盘用于存储文档缓存、操作历史、转换临时文件,建议使用 SSD 以保证 I/O 性能
- 内存是最容易成为瓶颈的资源,不要为了省钱压低内存配置
2.2 操作系统
推荐 Ubuntu 22.04 LTS 或 Debian 11/12。CentOS 系列亦可,但部分包名和服务管理命令略有差异,本文不单独列出。
2.3 安装 Docker 与 Docker Compose
# 卸载旧版本(如有)sudo apt remove docker docker-engine docker.io containerd runc# 安装依赖sudo apt updatesudo apt install -y ca-certificates curl gnupg lsb-release# 添加 Docker 官方 GPG Keysudo mkdir -p /etc/apt/keyringscurl -fsSL https://download.docker.com/linux/ubuntu/gpg \ | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg# 添加 Docker 软件源echo "deb [arch=$(dpkg --print-architecture) \ signed-by=/etc/apt/keyrings/docker.gpg] \ https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" \ | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null# 安装 Docker Engine 和 Compose 插件sudo apt updatesudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin# 将当前用户加入 docker 组,避免每次使用 sudosudo usermod -aG docker $USERnewgrp docker# 验证安装docker --versiondocker compose version2.4 目录结构规划
在开始之前,先规划好目录结构,后续所有配置都以此为基础:
mkdir -p /opt/onlyoffice/{data,logs,config,certs}mkdir -p /opt/onlyoffice/data/{documentserver,postgresql,rabbitmq,redis}# 目录用途说明:# /opt/onlyoffice/data/documentserver - 文档缓存与临时文件# /opt/onlyoffice/data/postgresql - 数据库持久化数据# /opt/onlyoffice/data/rabbitmq - 消息队列持久化数据# /opt/onlyoffice/data/redis - Redis 持久化数据(可选)# /opt/onlyoffice/logs - 所有服务的日志# /opt/onlyoffice/config - 自定义配置文件# /opt/onlyoffice/certs - SSL 证书3. Docker Compose 完整部署
3.1 创建 Docker Compose 文件
在 /opt/onlyoffice 目录下创建 docker-compose.yml:
version: "3.8"services: # ─── PostgreSQL ─────────────────────────────────────────────── postgresql: image: postgres:14-alpine container_name: onlyoffice-postgresql restart: unless-stopped environment: POSTGRES_DB: onlyoffice POSTGRES_USER: onlyoffice POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} # 从 .env 读取 volumes: - /opt/onlyoffice/data/postgresql:/var/lib/postgresql/data networks: - onlyoffice-net healthcheck: test: ["CMD-SHELL", "pg_isready -U onlyoffice"] interval: 10s timeout: 5s retries: 5 # ─── RabbitMQ ───────────────────────────────────────────────── rabbitmq: image: rabbitmq:3.12-management-alpine container_name: onlyoffice-rabbitmq restart: unless-stopped environment: RABBITMQ_DEFAULT_USER: onlyoffice RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD} volumes: - /opt/onlyoffice/data/rabbitmq:/var/lib/rabbitmq networks: - onlyoffice-net healthcheck: test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"] interval: 15s timeout: 10s retries: 5 # ─── Redis ──────────────────────────────────────────────────── redis: image: redis:7-alpine container_name: onlyoffice-redis restart: unless-stopped command: redis-server --requirepass ${REDIS_PASSWORD} --save 60 1 volumes: - /opt/onlyoffice/data/redis:/data networks: - onlyoffice-net healthcheck: test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"] interval: 10s timeout: 5s retries: 5 # ─── OnlyOffice Document Server ─────────────────────────────── onlyoffice-documentserver: image: onlyoffice/documentserver:latest container_name: onlyoffice-documentserver restart: unless-stopped depends_on: postgresql: condition: service_healthy rabbitmq: condition: service_healthy redis: condition: service_healthy environment: # 数据库连接 DB_TYPE: postgres DB_HOST: postgresql DB_PORT: 5432 DB_NAME: onlyoffice DB_USER: onlyoffice DB_PWD: ${POSTGRES_PASSWORD} # RabbitMQ 连接 AMQP_TYPE: rabbitmq AMQP_URI: amqp://onlyoffice:${RABBITMQ_PASSWORD}@rabbitmq # Redis 连接 REDIS_SERVER_HOST: redis REDIS_SERVER_PORT: 6379 REDIS_SERVER_PASS: ${REDIS_PASSWORD} # JWT 安全(生产环境必须启用) JWT_ENABLED: "true" JWT_SECRET: ${JWT_SECRET} JWT_HEADER: Authorization JWT_IN_BODY: "false" # 文档服务基础配置 ALLOW_META_IP_ADDRESS: "false" ALLOW_PRIVATE_IP_ADDRESS: "false" volumes: - /opt/onlyoffice/data/documentserver:/var/www/onlyoffice/Data - /opt/onlyoffice/logs:/var/log/onlyoffice - /opt/onlyoffice/config:/etc/onlyoffice/documentserver ports: - "127.0.0.1:8080:80" # 仅监听本地,通过 Nginx 反代暴露 networks: - onlyoffice-netnetworks: onlyoffice-net: driver: bridge3.2 创建环境变量文件
在同目录下创建 .env 文件,存放敏感配置:
# /opt/onlyoffice/.env# 生产环境请使用强密码,以下为示例POSTGRES_PASSWORD=your_strong_postgres_password_hereRABBITMQ_PASSWORD=your_strong_rabbitmq_password_hereREDIS_PASSWORD=your_strong_redis_password_hereJWT_SECRET=your_long_random_jwt_secret_at_least_32_chars生成强随机密码的便捷命令:
# 生成 32 位随机密码openssl rand -base64 32# 生成适合 JWT Secret 的 64 位随机字符串openssl rand -hex 32.env 文件权限必须收紧:
chmod 600 /opt/onlyoffice/.env3.3 启动服务
cd /opt/onlyoffice# 首次启动(后台运行)docker compose up -d# 查看启动日志,确认各服务正常docker compose logs -f --tail=50# 查看各容器状态docker compose ps首次启动时,Document Server 会执行数据库初始化,这个过程需要约 30–60 秒。观察日志,待出现以下内容时说明启动完成:
onlyoffice-documentserver | ServerInfo: nodeJS version - v18.x.xonlyoffice-documentserver | Watcher: Listening on port 80003.4 验证服务状态
# 检查 Document Server 健康状态curl -s http://localhost:8080/healthcheck# 预期返回# true如果返回 true,说明 Document Server 本体正常运行。
Docker直接部署
docker run -d -p 7080:80 \-v /opt/onlyoffice/DocumentServer/logs:/var/log/onlyoffice \-v /opt/onlyoffice/DocumentServer/data:/var/www/onlyoffice/Data \-v /opt/onlyoffice/DocumentServer/lib:/var/lib/onlyoffice \-v /opt/onlyoffice/DocumentServer/rabbitmq:/var/lib/rabbitmq \-v /opt/onlyoffice/DocumentServer/redis:/var/lib/redis \-v /opt/onlyoffice/DocumentServer/db:/var/lib/postgresql \-e JWT_ENABLED=false \-e ALLOW_PRIVATE_IP_ADDRESS=true \--name onlyoffice \ onlyoffice/documentserver4. Nginx 反向代理与 SSL 配置
Document Server 的端口(8080)不应直接对外暴露,生产环境必须通过 Nginx 反向代理,同时处理 SSL 终止。
4.1 安装 Nginx 与 Certbot
sudo apt install -y nginx certbot python3-certbot-nginx4.2 获取 SSL 证书
如果你有域名,使用 Let's Encrypt 免费证书:
# 将 docs.example.com 替换为你的实际域名sudo certbot certonly --nginx -d docs.example.com证书文件位置:
- 证书:/etc/letsencrypt/live/docs.example.com/fullchain.pem
- 私钥:/etc/letsencrypt/live/docs.example.com/privkey.pem
如果是内网部署无法使用 Let's Encrypt,使用自签名证书:
sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \ -keyout /opt/onlyoffice/certs/onlyoffice.key \ -out /opt/onlyoffice/certs/onlyoffice.crt \ -subj "/CN=docs.example.com"4.3 Nginx 配置文件
创建 /etc/nginx/sites-available/onlyoffice:
# HTTP → HTTPS 重定向server { listen 80; server_name docs.example.com; return 301 https://$host$request_uri;}# HTTPS 主配置server { listen 443 ssl http2; server_name docs.example.com; # SSL 证书(Let's Encrypt 路径,自签名证书修改为对应路径) ssl_certificate /etc/letsencrypt/live/docs.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/docs.example.com/privkey.pem; # SSL 安全配置 ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers off; ssl_session_timeout 1d; ssl_session_cache shared:SSL:10m; ssl_stapling on; ssl_stapling_verify on; # 安全 Headers add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always; add_header X-Content-Type-Options nosniff; add_header X-Frame-Options SAMEORIGIN; # 上传文件大小限制(根据实际需求调整) client_max_body_size 100m; # Gzip 压缩(减少静态资源传输量) gzip on; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; gzip_min_length 1000; # 代理到 Document Server location / { proxy_pass http://127.0.0.1:8080; proxy_http_version 1.1; # WebSocket 支持(协同编辑必须) proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; # 传递真实客户端信息 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_read_timeout 3600; proxy_connect_timeout 3600; proxy_send_timeout 3600; }}4.4 启用配置
sudo ln -s /etc/nginx/sites-available/onlyoffice \ /etc/nginx/sites-enabled/onlyoffice# 测试配置文件语法sudo nginx -t# 重载 Nginx(不中断现有连接)sudo nginx -s reload4.5 SSL 证书自动续期
Let's Encrypt 证书有效期 90 天,Certbot 安装后会自动创建续期定时任务。验证续期逻辑:
# 测试续期流程(不实际续期)sudo certbot renew --dry-run5. 核心配置文件详解
OnlyOffice Document Server 的主配置文件是 local.json,位于容器内的 /etc/onlyoffice/documentserver/local.json。通过 Docker Compose 中的 volume 挂载,我们可以在宿主机的 /opt/onlyoffice/config/local.json 编辑它。
local.json 是覆盖式配置,只需写入你想修改的项,其余项会自动继承默认值。以下是常用的配置项说明:
{ "services": { "CoAuthoring": { "server": { "port": 8000, "limits": { "connectionAndMeta": "20mb", "postSize": "2mb", "customizationElements": 10 } }, "sql": { "type": "postgres", "dbHost": "postgresql", "dbPort": 5432, "dbName": "onlyoffice", "dbUser": "onlyoffice", "dbPass": "your_password" }, "token": { "enable": { "request": { "inbox": true, "outbox": true }, "browser": true }, "inbox": { "header": "Authorization", "inBody": false }, "outbox": { "header": "Authorization" } }, "autoAssembly": { "enable": true, "interval": "5m" } } }, "FileConverter": { "converter": { "maxprocesscount": 4, "limit": { "filesize": 104857600 } } }, "storage": { "fs": { "secretString": "your_storage_secret", "folderPath": "/var/www/onlyoffice/Data" } }, "log": { "filePath": "/var/log/onlyoffice/documentserver" }}重要配置项说明:
autoAssembly:控制文档自动保存(Force Save)的行为。enable: true 表示在用户编辑期间,Document Server 会按 interval 指定的间隔自动触发回调,将文档保存到集成方。推荐生产环境开启,可以减少因服务中断导致的数据丢失。
maxprocesscount:转换服务的最大并行转换进程数。默认值通常等于 CPU 核数,过高会在批量转换时导致 CPU 打满,建议设置为 CPU 核数的 50%–75%。
filesize:允许处理的最大文件大小(字节),100 MB 是一个合理的起点,过大的文件会显著消耗内存和 CPU。
修改 local.json 后,需要重启 Document Server 容器使配置生效:
docker compose restart onlyoffice-documentserver6. JWT 安全配置
在第二篇中介绍了 JWT 的原理,本节给出具体的配置与验证步骤。
6.1 Document Server 侧配置
在 Docker Compose 的 environment 中,已经配置了 JWT 相关环境变量:
JWT_ENABLED: "true"JWT_SECRET: ${JWT_SECRET}JWT_HEADER: Authorization这里有一个容易混淆的细节:JWT_HEADER 指定 JWT Token 通过哪个 HTTP Header 传递。默认值 Authorization 意味着集成方需要将 Token 放在 Authorization: Bearer
6.2 集成方侧的 JWT 签名实现
集成方需要用相同的 Secret 对编辑器配置进行签名。以下是各语言的实现示例:
Node.js(使用 jsonwebtoken 库):
const jwt = require('jsonwebtoken');const jwtSecret = process.env.JWT_SECRET;// 生成编辑器配置的 JWT Tokenfunction generateEditorConfig(fileUrl, fileKey, userId, userName, callbackUrl) { const config = { document: { fileType: 'docx', key: fileKey, // 文档唯一标识,修改后必须更换 title: '文档标题.docx', url: fileUrl, // Document Server 拉取文件的地址 permissions: { edit: true, download: true, print: true, comment: true, review: true } }, editorConfig: { callbackUrl: callbackUrl, // 保存回调地址 user: { id: userId, name: userName }, lang: 'zh', mode: 'edit' } }; // 签名配置,生成 token const token = jwt.sign(config, jwtSecret, { algorithm: 'HS256' }); // 将 token 附加到配置中返回给前端 return { ...config, token };}Python(使用 PyJWT 库):
import jwtimport osjwt_secret = os.environ.get('JWT_SECRET')def generate_editor_config(file_url, file_key, user_id, user_name, callback_url): config = { 'document': { 'fileType': 'docx', 'key': file_key, 'title': '文档标题.docx', 'url': file_url, 'permissions': { 'edit': True, 'download': True, 'comment': True, } }, 'editorConfig': { 'callbackUrl': callback_url, 'user': { 'id': user_id, 'name': user_name }, 'lang': 'zh', 'mode': 'edit' } } token = jwt.encode(config, jwt_secret, algorithm='HS256') return {**config, 'token': token}Java(使用 jjwt 库):
import io.jsonwebtoken.Jwts;import io.jsonwebtoken.SignatureAlgorithm;import java.util.Map;import java.util.HashMap;public class OnlyOfficeJwtHelper { private final String jwtSecret; public OnlyOfficeJwtHelper(String jwtSecret) { this.jwtSecret = jwtSecret; } public String generateToken(Map config) { return Jwts.builder() .setClaims(config) .signWith(SignatureAlgorithm.HS256, jwtSecret.getBytes()) .compact(); }}6.3 回调验签
Document Server 向集成方发送保存回调时,会在 Authorization Header 中携带 JWT Token。集成方必须验签后才能处理回调,否则存在被伪造的风险:
// Node.js Express 示例const jwt = require('jsonwebtoken');app.post('/onlyoffice/callback', (req, res) => { const authHeader = req.headers['authorization']; if (!authHeader || !authHeader.startsWith('Bearer ')) { return res.status(401).json({ error: 1, message: 'Missing JWT token' }); } const token = authHeader.slice(7); try { const decoded = jwt.verify(token, process.env.JWT_SECRET); // 验签通过,处理回调 handleCallback(decoded, req.body); res.json({ error: 0 }); } catch (err) { console.error('JWT verification failed:', err.message); res.status(401).json({ error: 1, message: 'Invalid JWT token' }); }});7. 性能调优
7.1 连接数限制调整
Document Server 默认对单个文档的并发连接数有限制。在高并发场景下,可能需要调整:
在 local.json 中添加:
{ "services": { "CoAuthoring": { "server": { "limits": { "connectionAndMeta": "50mb", "postSize": "10mb" }, "connections": 100 } } }}7.2 内存配置
Node.js 默认的 V8 堆内存上限约为 1.5 GB,在处理大量并发连接时可能不够。通过环境变量调整:
在 Docker Compose 中为 Document Server 添加:
environment: NODE_OPTIONS: "--max-old-space-size=4096" # 4 GB,根据实际内存调整7.3 PostgreSQL 调优
对于承载 OnlyOffice 的 PostgreSQL 实例,几个关键参数的调整:
创建 /opt/onlyoffice/config/postgresql.conf(通过 volume 挂载到容器):
# 内存配置(根据服务器内存调整,以 16 GB 内存为例)shared_buffers = 2GB # 约总内存的 25%effective_cache_size = 6GB # 约总内存的 50%–75%work_mem = 16MB # 每个查询操作的工作内存maintenance_work_mem = 256MB # 维护操作(VACUUM、CREATE INDEX)内存# WAL 配置wal_buffers = 16MBcheckpoint_completion_target = 0.9# 连接配置max_connections = 200 # 根据并发需求调整7.4 Redis 持久化配置
Redis 的默认 RDB 持久化在大量写入时会影响性能。对于 OnlyOffice 的使用场景(会话缓存为主),可以降低持久化频率:
在 Docker Compose 的 Redis 启动命令中调整:
command: > redis-server --requirepass ${REDIS_PASSWORD} --save 900 1 --save 300 10 --maxmemory 1gb --maxmemory-policy allkeys-lrumaxmemory-policy allkeys-lru 表示当内存达到上限时,自动淘汰最久未使用的 Key,避免 Redis 内存溢出。
7.5 Nginx 优化
在 Nginx 的 http 块中添加以下配置:
# 工作进程数(通常等于 CPU 核数)worker_processes auto;# 每个工作进程的最大连接数events { worker_connections 4096; use epoll;}http { # 开启 sendfile,减少内核态/用户态切换 sendfile on; tcp_nopush on; tcp_nodelay on; # Keep-Alive 连接超时 keepalive_timeout 65; keepalive_requests 1000; # 缓冲区大小(处理大型请求头) proxy_buffer_size 128k; proxy_buffers 4 256k; proxy_busy_buffers_size 256k;}8. 监控与日志
8.1 日志文件位置与结构
Document Server 的日志写入 /opt/onlyoffice/logs(通过 volume 挂载),目录结构如下:
/opt/onlyoffice/logs/├── documentserver/│ ├── out.log # 主进程标准输出(服务启动、重要事件)│ ├── err.log # 错误日志(重点关注)│ ├── docservice.log # 文档服务日志(连接、会话事件)│ ├── converter.log # 格式转换日志│ └── notification.log # 回调通知日志日常排查问题首先查看 err.log 和 docservice.log。
8.2 接入 Prometheus + Grafana
Document Server 7.0 以上版本内置了 Prometheus 指标端点,开启方式:
在 local.json 中添加:
{ "statsd": { "useMetrics": true, "host": "0.0.0.0", "port": 9090 }}然后在 Prometheus 的 scrape_configs 中添加:
scrape_configs: - job_name: 'onlyoffice' static_configs: - targets: ['your-server-ip:9090'] metrics_path: '/metrics'关键监控指标:
| 指标名 | 含义 | 告警建议 |
|---|---|---|
| onlyoffice_active_connections | 当前活跃连接数 | 接近硬件上限时告警 |
| onlyoffice_conversion_errors | 转换失败次数 | 短时间内突增时告警 |
| onlyoffice_queue_length | 待处理消息队列长度 | 持续增长时告警 |
| process_resident_memory_bytes | 进程内存占用 | 接近配置上限时告警 |
8.3 健康检查接口
Document Server 提供了几个内置的健康检查接口,可以集成到你的监控系统:
# 基础健康检查GET /healthcheck# 返回 true(正常)或 false(异常)# 详细状态信息(需要 Document Server 7.2+)GET /info/info.json# 返回 JSON,包含版本、许可证状态、连接数等9. 升级策略与数据备份
9.1 升级前的准备
OnlyOffice 的版本升级需要谨慎,主要风险点有两个:
- 数据库 Schema 变更(新版本可能自动执行迁移,但不可逆)
- 配置文件格式变化(新版本可能废弃或修改某些配置项)
升级前必须完整备份数据:
# 1. 备份 PostgreSQL 数据库docker exec onlyoffice-postgresql pg_dump \ -U onlyoffice onlyoffice > \ /opt/onlyoffice/backup/postgresql_$(date +%Y%m%d_%H%M%S).sql# 2. 备份 Document Server 数据卷tar -czf /opt/onlyoffice/backup/documentserver_data_$(date +%Y%m%d_%H%M%S).tar.gz \ /opt/onlyoffice/data/documentserver# 3. 备份配置文件cp /opt/onlyoffice/config/local.json \ /opt/onlyoffice/backup/local.json.$(date +%Y%m%d_%H%M%S)9.2 滚动升级步骤
cd /opt/onlyoffice# 第一步:拉取新版镜像docker compose pull onlyoffice-documentserver# 第二步:停止服务(选择业务低峰期)docker compose stop onlyoffice-documentserver# 第三步:启动新版本(Docker Compose 会使用新镜像重建容器)docker compose up -d onlyoffice-documentserver# 第四步:观察启动日志,确认服务正常docker compose logs -f onlyoffice-documentserver# 第五步:执行健康检查curl -s http://localhost:8080/healthcheck如果新版本出现问题,回滚方式:
# 指定回滚到具体版本(例如 7.5.0)# 修改 docker-compose.yml 中的镜像版本# image: onlyoffice/documentserver:7.5.0docker compose up -d onlyoffice-documentserver9.3 自动备份脚本
创建 /opt/onlyoffice/scripts/backup.sh:
#!/bin/bashset -euo pipefailBACKUP_DIR="/opt/onlyoffice/backup"TIMESTAMP=$(date +%Y%m%d_%H%M%S)RETENTION_DAYS=7mkdir -p "$BACKUP_DIR"echo "[$(date)] 开始备份..."# 备份数据库docker exec onlyoffice-postgresql pg_dump \ -U onlyoffice onlyoffice \ > "$BACKUP_DIR/postgresql_${TIMESTAMP}.sql"# 压缩数据库备份gzip "$BACKUP_DIR/postgresql_${TIMESTAMP}.sql"# 备份文档数据tar -czf "$BACKUP_DIR/data_${TIMESTAMP}.tar.gz" \ /opt/onlyoffice/data/documentserver \ /opt/onlyoffice/configecho "[$(date)] 备份完成:$BACKUP_DIR"# 删除超过保留天数的旧备份find "$BACKUP_DIR" -name "*.sql.gz" -mtime +$RETENTION_DAYS -deletefind "$BACKUP_DIR" -name "*.tar.gz" -mtime +$RETENTION_DAYS -deleteecho "[$(date)] 旧备份清理完成"chmod +x /opt/onlyoffice/scripts/backup.sh# 配置定时备份(每天凌晨 3 点执行)echo "0 3 * * * root /opt/onlyoffice/scripts/backup.sh >> /opt/onlyoffice/logs/backup.log 2>&1" \ | sudo tee /etc/cron.d/onlyoffice-backup10. 常见问题排查
问题一:编辑器页面空白或加载超时
症状: 集成方页面嵌入编辑器后,显示空白或一直转圈。
排查步骤:
# 1. 检查 Document Server 是否正常运行curl -s http://localhost:8080/healthcheck# 2. 检查 Nginx 日志sudo tail -100 /var/log/nginx/error.log# 3. 检查 WebSocket 代理是否正常(协同编辑依赖)# 在浏览器开发者工具的 Network 标签中,检查是否有 WebSocket 连接# 连接状态应为 101 Switching Protocols常见原因:
- Nginx 未配置 WebSocket 代理(缺少 Upgrade 和 Connection Header)
- JWT Secret 不匹配(集成方签名用的 Secret 与 Document Server 配置的不一致)
- Document Server 无法访问集成方提供的文件 URL(网络隔离或 URL 错误)
问题二:文档保存回调失败
症状: 用户关闭编辑器后,文件未更新到集成方存储,日志中出现回调错误。
排查步骤:
# 查看回调日志tail -100 /opt/onlyoffice/logs/documentserver/notification.log# 典型错误信息:# callback url returned code 404 → 回调 URL 路径错误# callback url returned code 401 → 集成方验签失败# callback url connection timeout → 集成方服务不可达或超时注意: Document Server 必须能够从内部访问集成方的回调 URL。如果集成方和 Document Server 在同一内网,使用内网地址;不要使用 localhost 作为回调地址(Document Server 容器内的 localhost 不是宿主机)。
问题三:大文件转换超时
症状: 大型 .xlsx 或 .docx 文件无法打开,日志显示转换超时。
解决方案:
调整 local.json 中的转换超时配置:
{ "FileConverter": { "converter": { "timeout": 600000, "limit": { "filesize": 209715200 } } }}同时调整 Nginx 的 proxy_read_timeout 和 proxy_send_timeout(见第 4 节),确保超时时间足够覆盖大文件转换。
问题四:内存持续增长
症状: Document Server 容器的内存占用随时间持续增长,最终 OOM。
排查与应对:
# 查看 Document Server 进程内存占用详情docker stats onlyoffice-documentserver# 检查是否有"僵尸"文档会话(编辑器已关闭但会话未释放)tail -f /opt/onlyoffice/logs/documentserver/docservice.log | grep "closeDocument"临时解决方案:配置容器重启策略和内存限制:
onlyoffice-documentserver: deploy: resources: limits: memory: 8G restart: unless-stopped根本解决:排查是否有集成方代码在文档保存回调中返回了错误,导致 Document Server 持续重试,会话无法正常关闭。
11. 生产环境检查清单
在将 OnlyOffice 服务推向生产环境之前,逐项确认以下清单:
安全配置
- JWT 已启用,Secret 使用强随机字符串(不少于 32 位)
- PostgreSQL 密码不为默认值,且不对外暴露端口
- RabbitMQ 和 Redis 密码已设置,端口不对外暴露
- Nginx 已配置 HTTPS,HTTP 自动重定向到 HTTPS
- SSL 证书有效,自动续期已配置
- Docker Compose 中 Document Server 端口仅绑定 127.0.0.1
- .env 文件权限为 600
- ALLOW_PRIVATE_IP_ADDRESS 在生产环境设为 false
功能验证
- /healthcheck 接口返回 true
- 可以正常打开 .docx、.xlsx、.pptx 文件
- 多用户协同编辑功能正常(光标可见、修改实时同步)
- 文档关闭后保存回调触发正常,文件已更新到集成方存储
- 格式转换 API 可用(测试 docx → pdf 转换)
- WebSocket 连接状态为 101(浏览器开发者工具确认)
运维准备
- 日志目录挂载正常,日志文件可读
- 自动备份脚本已配置并测试
- 监控告警已配置(至少覆盖服务存活和磁盘空间)
- 升级回滚方案已演练
- autoAssembly(自动保存)已在 local.json 中启用
- 文档大小限制已根据业务需求调整
性能基准
- 已进行压测,了解当前配置下的并发上限
- 磁盘使用量监控已配置,避免缓存文件撑满磁盘
- 已记录基线资源使用(CPU、内存、磁盘 I/O)
小结
本文覆盖了 OnlyOffice Docs 从部署到生产的完整链路,核心要点回顾:
部署层面采用 Docker Compose 多服务编排,各组件(PostgreSQL、RabbitMQ、Redis、Document Server)独立运行,便于维护和扩展。Nginx 承担反向代理、SSL 终止和静态资源优化的职责,Document Server 本身不直接暴露给外部。
安全方面,JWT 是必须启用的配置项,同时所有数据库服务只在 Docker 内部网络中通信,不对宿主机外暴露端口。
运维方面,自动备份、定期健康检查和监控指标接入是保障服务稳定性的基础投入,在实际出问题之前完成这些配置,远比出了问题再补救代价低。
夜雨聆风