使用Docker部署NextCloud和Onlyoffice

使用Docker部署NextCloud和Onlyoffice

Nextcloud 是目前最流行的开源私有云盘方案,而 OnlyOffice 提供了强大的在线文档编辑能力。两者结合可以实现文档在线编辑和协作。

但在实际部署中,会遇到很多问题,本文记录部署过程和一些问题及解决方法。

环境准备

环境介绍

以下是我使用的硬件和软件情况

项目 版本
架构 x64
CPU核心 8核
内存 16G
操作系统 Linux(Fedora 43)
Docker Docker version 29.5.3
Docker Compose Docker Compose version v5.1.4

硬件要求

项目 要求
内存 4G以上(推荐8G)
磁盘 20G以上可用空间

使用镜像

服务 镜像
Nextcloud linuxserver/nextcloud:34.0.0
onlyoffice onlyoffice/documentserver:9.4.0.1

拉取镜像

可以先不用拉取镜像,使用compose部署会自动拉取

docker pull linuxserver/nextcloud:34.0.0
docker pull onlyoffice/documentserver:9.4.0.1

检查环境:

使用以下命令检查docker/docker compose

docker --v
docker compose version

输出版本即表示docker已安装,如果没有安装,需要安装一下可以参考Linux一键安装Docker

文件准备

运行目录

安装nextcloud和onlyoffice之前,先创建运行目录

mkdir -p /data/container/nextcloud-onlyoffice && cd /data/container/nextcloud-onlyoffice

docker-compose.yml

vim docker-compose.yml

写入以下内容

services:
  # ===== Nextcloud (linuxserver 镜像) =====
  nextcloud:
    image: linuxserver/nextcloud:34.0.0
    container_name: nextcloud
    restart: unless-stopped
    ports:
      - "8080:80"
      - "8443:443"   # HTTPS 端口(可选)
    volumes:
      - ./nextcloud/config:/config   # Nextcloud 程序 + 配置
      - ./nextcloud/data:/data       # 用户数据
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    networks:
      - 1panel-network

  # ===== OnlyOffice Document Server =====
  onlyoffice:
    image: onlyoffice/documentserver:latest
    container_name: onlyoffice
    restart: unless-stopped
    ports:
      - "8090:80"
    volumes:
      - ./onlyoffice/data:/var/www/onlyoffice/Data
      - ./onlyoffice/config:/etc/onlyoffice/documentserver
      - ./onlyoffice/logs:/var/log/onlyoffice
      - ./onlyoffice/fonts:/usr/share/fonts/truetype/custom
    environment:
      # ⭐ 关键:必须手动指定 JWT 密钥(否则重启后密钥变化导致连接断开)
      - JWT_SECRET=${JWT_SECRET}
      - JWT_HEADER=${JWT_HEADER}
      - JWT_ENABLED=true
      - ALLOW_PRIVATE_IP_ADDRESS=true
      - TZ=${TZ}
    networks:
      - 1panel-network

# ==== 网络,我的redis和mysql使用1panel部署的,使用同一网络
networks:
	1panel-network: 
		external: true

环境变量

vim .env

写入以下内容,按需修改

# ===== Nextcloud 配置 =====
# ===== 用户权限=====
PUID=1000
PGID=1000
# ===== OnlyOffice JWT 密钥(如果启用必须手动指定,否则容器重启后会重新生成导致连接断开)=====
JWT_SECRET=你的随机密钥至少32位
JWT_HEADER=AuthorizationJwt

# ===== 时区 =====
TZ=Asia/Shanghai

准备中文字体

onlyoffice缺少中文字体(应该是有的,但是仅仅能显示中文而已,常用的字体基本都没有)。准备字体文件,在 /data/container/nextcloud-onlyoffice目录下新建 onlyoffice/fonts目录(docker-compose.yml中指定的目录),将字体文件放在该目录

初始化

启动容器

完成compose和.env后,启动容器

docker compose up -d

等待容器创建并启动,如果前边没有拉取镜像,这里会自动拉取

初始化Nextcloud

初始化之前可以先配置以下域名,自行配置nginx代理(抽空补充)。

使用浏览器访问http://<your_ip>:<nextcloud_http_port>或者配置的域名,设置管理员用户名和密码,并输入数据库信息,这里使用MySQL/MariaDB(我只比较熟悉MySQL)数据库需要提前创建。如果数据库使用root用户,不提前创建也行,不过不能与已有数据库名重复。

等待初始化完成,会展示推荐的应用,直接跳过,随后再安装

集成onlyoffice

进入NextCloud后,点击头像 --> 应用,找到Office & Text,点一下Nextcloud Office,输入密码开始安装。

image-1781780249813.png

安装完成后点击头像 --> 管理设置,找到ONLYOFFICE,填写配置项,然后点保存即可。如果保存报错 连接时发生异常 (文档服务内部发生异常: Error while downloading the document file to be converted.),可以查看配置可信域名

ONLYOFFICE Docs地址:http://<your_ip>:<onlyoffice_http_port> ## 或nginx配置的onlyoffice域名,如果要公网访问,必须使用域名或者有公网IP直接使用公网IP也行,推荐域名。如果只是局域网使用,ip:端口即可
秘钥: .env中设置的JWT_SECRET
授权标头: .env中设置的JWT_HEADER
服务器内部请求 ONLYOFFICE Docs 的地址: http://onlyoffice容器名
ONLYOFFICE Docs 内部请求服务器的地址: http://nextcloud容器名

image-1781780416207.png

完善配置

安装好之后,实际上使用过程中还会遇到一些问题,下面列出一些我遇到的问题及解决方案(有些其实也没有完全解决,也是能用就凑合着用了),还有一些优化的配置。

配置可信域名

Nextcloud 默认只允许初始化时的域名或 IP 访问,通过其他 IP 或域名访问时会提示"通过不受信任的域访问"。前边集成ONlyOffice提到的报错其实也是这个原因。添加信任的域名即可。

方案一:通过occ命令添加

# 查看当前可信域名
docker exec nextcloud occ config:system:get trusted_domains

# 添加新的可信域名
docker exec Nextcloud occ config:system:set trusted_domains 1 --value=cloud.example.com # nginx中配置的域名
docker exec Nextcloud occ config:system:set trusted_domains 2 --value=nextcloud # Nextcloud容器名
docker exec Nextcloud occ config:system:set trusted_domains 2 --value=192.168.0.100 # Nextcloud所在服务器的局域网IP

方案二:直接编辑配置文件

  1. 进入容器运行目录:
cd /data/container/nextcloud-onluoffice
  1. 编辑配置文件 config.php:
vim nextcloud/config/www/nextcloud/config/config.php
  1. 按照下面的修改,把需要访问Nextcloud
'trusted_domains' => 
  array (
    0 => 'cloud.example.com', // nginx中配置的域名
    1 => 'Nextcloud', // Nextcloud容器名
    2 => '192.168.0.100', // Nextcloud所在服务器的局域网IP
  ),

添加后再使用trusted_domains中的域名或IP访问就不会报错了,ONlyOffice的连接报错也解决了。

准备中文字体

如果启动容器之前准备好了字体,可以跳过

OnlyOffice缺少中文字体(应该是有的,但是仅仅能显示中文而已,常用的字体基本都没有)。准备字体文件,在 /data/container/nextcloud-onluoffice目录下新建 ONlyOffice/fonts目录(docker-compose.yml中指定的目录),将字体文件放在该目录。

重建OnlyOffice

cd /data/container/nextcloud-onluoffice
docker compose stop onluoffice && docker rm onluoffice && docker compose up -d onluoffice

或者两个容器全都重建,数据已经持久化到宿主机,不会丢失

cd /data/container/nextcloud-onluoffice
docker compose down && docker compose up -d

重建字体缓存

理论上重建容器之后字体会立即生效,可以执行以下命令查看一下,如果输出了添加的字体,就不用执行重建缓存命令了

fc-list :lang=zh

如果没有添加的字体,执行以下命令,等待执行完成即可

docker exec -it onluoffice bash /usr/bin/documentserver-generate-allfonts.sh

Nextcloud显示真实IP

如果使用nginx代理,可能会出现Nextcloud中显示的访问IP为nginx服务器IP,如图中所示,Nextcloud显示的IP是我的nginx服务器在OpenVPN虚拟虚拟局域网中的IP,即使nginx配置了转发真实IP,也没有生效。

image

原因是请求经过了 客户端 → 公网 Nginx → OpenVPN 隧道 → 内网 Nextcloud 的多层转发。Nginx 虽然设置了 X-Forwarded-For,但 OpenVPN 隧道会建立一个新的 TCP 连接,导致 remote_addr 变成 VPN 虚拟 IP。内网的 Nextcloud 需要正确信任代理链才能获取到真实 IP。使用其他组网方案会不会有这个问题我没有尝试,如果有,也可以尝试这个方案。

修改config.php配置文件,添加如下配置

'trusted_proxies' =>
  array (
    0 => '10.0.0.1/24',   // OpenVPN 虚拟网段 或 局域网网段
    1 => '172.16.0.0/12', // Docker 内部网段
  ),

修改后保存即可生效,不必重启容器

image

配置Redis

修改config.php配置文件,添加Redis连接配置

'memcache.local' => '\\OC\\Memcache\\Redis',
  'memcache.distributed' => '\\OC\\Memcache\\Redis',
  'memcache.locking' => '\\OC\\Memcache\\Redis',
  'redis' =>
    array (
      'host' => '你的Redis容器名或IP',  // 如 redis、172.18.0.5 等
      'password' => '你的Redis密码',
      'port' => 6379,
    ),

解决概览中的警告

打开管理设置-->概览,可以看到有很多警告信息,⚠是功能缺失和安全隐患,ℹ是优化建议。其中“日志中的错误”可以不用管。处理了日志中的错误这个警告也会在,除非将日志清理掉。

这里只解决⚠。

image-20260623161536900

维护窗口启动

这个警告的意思是,Nextcloud 目前不知道你的服务器在什么时间段访问量最少,因此一些消耗资源的后台任务(比如清理临时文件、生成缩略图)可能会在用户活跃的时间段运行,影响使用体验。要解决这个问题,可以设置maintenance_window_start参数,假设希望任务在凌晨3点执行,在config.php中添加:

'maintenance_window_start' => 19,

因为Nextcloud使用UTC时间,所以北京时间需要-8

可用的 Mimetype 迁移

这个设计主要是出于性能考量。当 Nextcloud 升级后,系统可能会引入新的 MIME 类型来更准确地识别文件。对于文件数量庞大的实例,这种数据库迁移可能会消耗较多资源,所以官方没有在升级时自动执行,而是将它设计成了一个需要管理员确认的手动操作。

根据提示执行命令即可

docker exec -it nextcloud occ maintenance:repair --include-expensive

HTTP标头

如果只在局域网中使用,没有配置域名和SSL证书,可以跳过这个。

这个安全警告意味着你的 Nextcloud 服务器没有发送 Strict-Transport-Security (HSTS) 这个关键的 HTTP 响应头。配置它可以让浏览器强制使用 HTTPS 访问你的站点,有效防范中间人攻击。

修复方法是在Nginx中配置中添加一个响应头:

## 在server块中添加
add_header Strict-Transport-Security "max-age=63072000" always

需要注意的一点是,只在nginx代理服务器中配置,警告并不会消失,在容器内的nginx配置也要同步添加,修改文件nextcloud/data/config/nginx/ssl.conf

修改后重载配置:

docker exec -it nextcloud nginx -s reload

Nextcloud卡死的解决

我在使用时遇到Nextcloud时不时就卡死的问题,网络上查找相关解决方案没什么收获,就跟着AI一通改,根本原因目前不是很清楚,但是修改之后确实很少再出现了,先记录一下,以后再遇到在研究。

下边是几个可能的原因

内存不足

Nextcloud + OnlyOffice对内存的要求是比较高的,如果内存不足,上传大文件或OnlyOffice转换时可能会OOM。不过我的内存充足,且没有限制容器内存,应该不是这个问题(有可能是默认的配置有内存限制,没有深入研究)

字体缺失

这里使用的是linuxserver/nextcloud,默认是不含中文字体的,生成含中文文档缩略图时进程挂死,累积后耗尽 PHP-FPM 进程池导致卡死。但是Nextcloud 容器只在极少数场景下需要服务端字体(如内置 PDF 缩略图生成)。如果已用 OnlyOffice 处理文档预览,一般不需要配置。这个作为可选配置,参考OnlyOffice的中文字体配置。不为Nextcloud添加中文字体的话,勾选 使用ONLYOFFICE生成文档预览

image-20260622105935351

PHP 内存不足

与上述内存不足不太一样,前边提到的内存不足是容器内存不足,这里的PHP内存指的是设置的内存限制。修改配置文件 nextcloud/config/php/www2.ini

; ===== 上传和文件大小限制 / Upload and file size limits =====
upload_max_filesize = 10G
post_max_size = 10G
max_input_time = 3600
max_execution_time = 3600

; ===== 内存限制 / Memory limit =====
memory_limit = 1024M

; ===== OPcache 优化(大幅提升性能)/ OPcache optimization =====
opcache.enable=1
opcache.interned_strings_buffer=32
opcache.max_accelerated_files=10000
opcache.memory_consumption=256
opcache.save_comments=1
opcache.revalidate_freq=1

上传文件大小的配置,如果使用了Nginx反向代理,需同步配置

client_max_body_size 10G;
client_body_timeout 3600s;
client_header_timeout 3600s;
proxy_read_timeout 3600s;
proxy_connect_timeout 3600s;
proxy_send_timeout 3600s;

数据库死锁

Nextcloud 默认用数据库锁,并发时死锁/长等待,这是最常见的卡死原因,使用Redis做文件锁,参考配置Redis添加Redis配置即可。

PHP-FPM 进程池耗尽

这个不是造成Nextcloud卡死的原因,而是上述问题造成了PHP-FPM 进程池耗尽从而导致Nextcloud卡死,通常表现为浏览器访问Nextcloud 502。

编辑 nextcloud/config/php/www2.ini,调整 PHP-FPM 进程数:

; PHP-FPM 进程池配置 / PHP-FPM process pool
pm = dynamic
pm.max_children = 20        ; 最大子进程数 / max child processes
pm.start_servers = 4         ; 启动时进程数 / processes at startup
pm.min_spare_servers = 2     ; 最小空闲进程 / min spare processes
pm.max_spare_servers = 6     ; 最大空闲进程 / max spare servers
pm.max_requests = 500        ; 每个进程处理请求数后重启 / requests per process before respawn