日志
- 2023-07-30:最新版本(2023-07-29)的
nextcloud:fpm
存在bug,其build成full镜像后php的imap.so缺失从而导致初始化失败。具体见该issue:Unable to load dynamic library ‘imap.so’ · Issue #2037 · nextcloud/docker。推荐暂时使用2023-7-21或之前的nextcloud:fpm
来buildfpm-bensz
镜像。 - 2023-06-21:优化Nginx Proxy Manager的教程。感谢
@zeyueguo
的提醒。
前言
《Docker系列 搭建个人云盘服务nextcloud》中包含排障教程(
警告&Bug
小节),比如不安全URL、caldav解析、数据库丢失索引、无法预览常见格式的文件、无法上传>512M的文件等。有需要者自行食用。
之前我在《Docker系列 搭建个人云盘服务nextcloud》中描述了一种基于Apache网络服务器的Nextcloud部署方法,它相对简单,可以体验很多Nextcloud的日常功能。不过,如果你准备在一台性能较强的机器(CPU性能高、内存大、磁盘空间大)里安装Nextcloud,我更加推荐本文将要介绍的Nextcloud-FPM-FULL + Nginx服务器
方案。经过合理的配置,Nextcloud可以充分利(ya)用(zha)宿主机的性能,在响应速度和稳定性上有较大提升;功能也因为更多依赖的安装而更加强大,比如原生支持图片/视频的实时预览。
Nextcloud-FPM
使用 FastCGI 进程管理器 (FPM) 来处理 PHP 请求,包括文件同步、共享、用户管理等功能;但未集成 Web 服务器,因此需要用 Nginx 来处理对 Nextcloud 的请求。FULL
的概念主要来源于官方文档,即在布署Nextcloud时安装所有扩展功能的相关依赖,比如CRON via supervisor、bz2、imap、gmp、smbclient、ffmpeg、imagemagick 甚至是 LibreOffice[可选,默认禁用]等。
不同于以往使用别人制作好的镜像,我们将直接使用自定义的Dockerfile来生成一个本地镜像。自定义Dockerfile可以提供最大的自由度,这应该才是Nextcloud这种灵活而复杂的应用的最好安装方式了。实际上在Docker的高级用户中,基于Dockerfile的安装方式也是比较流行的。
值得注意的是,《Docker系列 搭建个人云盘服务nextcloud》安装的Nextcloud应该可以迁移至本方案中,但目前还没有测试成功(提示504 Gateway Time-out
错误)。所以已经使用了旧版安装方法的小伙伴要考虑一下是否有必要换新,毕竟重构数据也是挺麻烦的。我自己的数据不多(10G+),已经迁移过来了。从长远使用的角度看,本教程的方案是强烈推荐的,毕竟总有一天我们会拥有一台性能强大的机器!
闲话少说,下面咱们讲一下如何部署Nextcloud-FPM-FULL + Nginx服务器
吧!
测试环境
系统环境如下:
uname -a # Linux pveomv 5.19.17-2-pve #1 SMP PREEMPT_DYNAMIC PVE 5.19.17-2 (Sat, 28 Jan 2023 16:40:25 x86_64 GNU/Linux
docker --version # Docker version 23.0.5, build bc4487a
docker-compose --version # Docker Compose version v2.4.1
Nextcloud的版本号为26.0.2
,为2023-06-08时的最新版本。
准备工作
Nextcloud-fpm镜像
本教程使用的是这个镜像:
值得注意的是,官方仓库还有一个类似的镜像,叫fpm-alpine
。fpm
镜像基于基于Debian/PVE操作系统作为基础镜像,它提供更广泛的软件包支持和易用性,但镜像比较大;而fpm-alpine
基于 Alpine Linux 的操作系统作为基础镜像,它比较轻量一些。
我注意到fpm-alpine
管理www目录的用户是82:82
,与Debian系的33:33
不太一样;加上自己是在NAS里安装Nextcloud的,对磁盘容量并不敏感,故没有使用fpm-alpine
。我测试过这两个镜像,都是可以用的,大家根据实际情况选择即可。
我们创建一个工作目录:
work=~/docker/nextcloud-fpm
mkdir -p $work/custom; cd $work
克隆nextcloud/docker项目:
git clone https://github.com/nextcloud/docker.git
进入nextcloud-fpm
的Dockerfile目录:
cd $work/docker/.examples/dockerfiles/full/fpm
build这个镜像:
# docker build -t <容器名> <Dockerfile所在目录>
docker build -t nextcloud:fpm-bensz .
耐心等待。如果错误,一般是apt-get安装依赖的过程不顺利造成的(网络问题),重试直至成功即可。成功时会出现类似字样:
Successfully built 0339xxxxxxxx
Successfully tagged nextcloud:fpm-bensz
# 或者:
# => => writing image # sha256:9e2f042044d24aaxxx 0.0s
# => => naming to docker.io/library/nextcloud:fpm-bensz
如果你的网络环境不好,我也可以考虑将build好的镜像发布到gitee之类的地方。有需要的在评论区留言吧!
我们查看一下该镜像:
docker image list | grep -E 'fpm-bensz'
输出类似:
nextcloud fpm-bensz 033xxxx 3 minutes ago 1.4G
表明该image已经成功安装。如果之后有版本更新,先下线整个stack,然后git pull更新至最新版,再依上述步骤在本地build新镜像即可。强烈推荐RSShub订阅Nextcloud的docker镜像release更新。
部署脚本
地址:https://github.com/nextcloud/docker/tree/master/.examples/docker-compose/insecure/mariadb/fpm
我们主要基于Nextcloud的官方仓库进行布署。首先,进入insecure/mariadb/fpm
中:
请注意,这里的insecure
指的是本地部署后以http://局域网ip:端口
的方式访问Nextcloud,这是我们想要的,因为我的教程体系中常规使用Nginx Proxy Manager进行https反向代理。选mariadb
是因为我们将使用mysql或mariadb作为Nextcloud的后端数据库。
执行以下代码即可复制到docker stack的根目录:
cd $work/docker/.examples/docker-compose/insecure/mariadb/fpm && cp -rp * $work
Dockerfile
web
文件夹只有Dockerfile和nginx配置:
total 9.0K
-rw-r--r-- 1 root bensz 57 Jun 7 16:52 Dockerfile
-rw-r--r-- 1 root bensz 7.4K Jun 7 20:24 nginx.conf
Dockerfile要求安装一个nginx容器并使用定制好的nginx.conf。
nginx.conf
建议在nginx.conf文件中做一些修改,这是一个示例。具体如下:
这些改动可以帮助更好地通过Nextcloud的安全检查。
db.env
db.env
指定了MYSQL帐户信息等在多个docker app中会被用到的环境变量:
MYSQL_PASSWORD=
MYSQL_DATABASE=nextcloud
MYSQL_USER=nextcloud
在以往的教程中,我一般直接在docker-compose.yml重复地声明这些变量。但在一些有经验的docker使用者中,定义1个或多个*.env
文件是更加流行和方便的策略。感兴趣的小伙伴以后也可以多应用这个技巧!
www.conf
我们需要在custom
目录中创建一个www.conf,这是一个示例。它定义了Nextcloud-fpm中PHP的一些行为。在Nextcloud 26.0.2中,该文件在容器中的位置为/usr/local/etc/php-fpm.d/www.conf
。我对这个文件的理解也不多,但知道一些比较重要的参数。
在官方文档 Server tuning — Nextcloud latest Administration Manual latest documentation中有这个描述:For example on a machine with 4GB of RAM and 1GB of MySQL cache following values in your www.conf
file should work:
pm = dynamic
pm.max_children = 120
pm.start_servers = 12
pm.min_spare_servers = 6
pm.max_spare_servers = 18
目前,我在自己的NAS里也是使用这个配置。大致的原则就是pm.max_children
最大,而pm.start_servers
在pm.min_spare_servers
和pm.max_spare_servers
。它们定义了php并发请求的一些基础值和上下限;配置好可以增强Nextcloud在多并发场景的表现。
大家可以使用这个设置,然后根据日志调试。这些参数在www.conf
中的实际位置如下:
最后,记得修改一下文件夹的权限:
sudo chown -R 33:33 $work/custom
其它准备
最后,$work
目录的文件分布大致如下:
├── [ 3] custom
│ └── [ 22K] www.conf
├── [ 78] db.env
├── [1.6K] docker-compose.yml
└── [ 4] web
├── [ 57] Dockerfile
└── [7.4K] nginx.conf
如果你的VPS还使用了ufw等防火墙,要开放相应的端口。这里以1234
为例:
ufw allow 1234/tcp comment 'nextcloud-fpm' && ufw reload
如果VPS后台管理中还有其它防火墙,也要依次放行。
准备好域名解析,比如nextcloudtest.hwb0307.com
。
安装Nextcloud-fpm
db.env
修改文件:
vim $work/db.env
自定义MYSQL数据库的相关信息,比如:
MYSQL_PASSWORD=test0test0!
MYSQL_DATABASE=nextcloud
MYSQL_USER=nextcloud
实际使用时一般是这样调用:
env_file:
- db.env
docker-compose.yml
我们在原版的基础上进行了优化,大家要根据实际情况微调:
version: '3'
services:
db:
# image: mariadb:10.6.5-focal # mariadb和mysql二选一即可
image: mysql:8.0
container_name: nextcloud-fpm-db
command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW --max-binlog-size=200M --expire-logs-days=2 # 优化mysql配置
restart: unless-stopped
volumes:
- ./db:/var/lib/mysql:Z
environment:
- MYSQL_ROOT_PASSWORD=nextclouddb_root_password
env_file:
- db.env
networks:
- default
cache:
image: redis:latest
container_name: nextcloud-fpm-cache
restart: unless-stopped
expose:
- "6379" # 可用此默认。因为这是暴露而不是映射
volumes:
- ./cache:/data
networks:
- default
app:
image: nextcloud:fpm-bensz
container_name: nextcloud-fpm-app
restart: unless-stopped
volumes:
- ./app:/var/www/html:z
- ./custom/www.conf:/usr/local/etc/php-fpm.d/www.conf
environment:
- MYSQL_HOST=db
- REDIS_HOST=cache
env_file:
- db.env
depends_on:
- db
- cache
networks:
- default
web:
build: ./web
container_name: nextcloud-fpm-web
restart: unless-stopped
ports:
- 1234:80 # 按需要修改
volumes:
- ./app:/var/www/html
depends_on:
- app
networks:
- default
cron:
image: nextcloud:fpm-bensz
container_name: nextcloud-fpm-cron
restart: unless-stopped
volumes:
- ./app:/var/www/html
entrypoint: /cron.sh
depends_on:
- db
- cache
networks:
- default
networks:
default:
name: nextcloud-fpm
请注意,在这里我指定了数据库的版本号mariadb:10.6.5-focal
或mysql:8.0
。你可以改为自己正在使用的版本号,这样比较节省空间。我个人比较推荐mysql,因为mysql可以随便转到mariadb中,但mariadb转到mysql里比较困难。
web
直接使用一个nginx:alpine镜像
+自定义nginx.conf。cron
就是利用nextcloud:fpm
中的/cron.sh
脚本自动配置后台作业。
然后,直接上线整个docker stack即可:
docker-compose up -d
在线安装
耐心等一段时间,之后访问 http://局域网ip:1234
即可。装的过程可能地址会失效,继续访问即可:
整个过程和旧版的安装过程是差不多的。
配置NPM
不了解Nginx Proxy Manager用法的小伙伴,请看《Docker系列 两大神器NPM和ddns-go的安装》。
ddns-go或者域名托管商后台解析好域名nextcloudtest.hwb0307.com
。假设NAS的局域网IP是192.168.1.123
。
添加一个Proxy Host,反代地址是http://192.168.1.123:1234
。可用泛域名的SSL证书。
最后,我们需要在Nginx Proxy Manager的Advanced里添加一些内容:
家用搭建的服务器一般是用别的端口来代替443。假设我们使用2443
作为Nginx Proxy Manager的默认443端口,那么添加内容为:
location /.well-known/carddav {
return 301 $scheme://$host:2443/remote.php/dav;
}
location /.well-known/caldav {
return 301 $scheme://$host:2443/remote.php/dav;
}
location /.well-known/webfinger {
return 301 $scheme://$host:2443/index.php/.well-known/webfinger;
}
location /.well-known/nodeinfo {
return 301 $scheme://$host:2443/index.php/.well-known/nodeinfo;
}
如果你使用的是默认的443端口,则不需要加端口号:
location /.well-known/carddav {
return 301 $scheme://$host/remote.php/dav;
}
location /.well-known/caldav {
return 301 $scheme://$host/remote.php/dav;
}
location /.well-known/webfinger {
return 301 $scheme://$host/index.php/.well-known/webfinger;
}
location /.well-known/nodeinfo {
return 301 $scheme://$host/index.php/.well-known/nodeinfo;
}
这些代码有助于通过Nextcloud的安全检查:
有时候webfinger
和nodeinfo
的安全警告会比较难以消失,可以通过退出帐号重新登陆或docker-compose down && docker-compose up -d
重新部署整个stack等方法进一步去除。
config.php
完成安装后,先不要正式使用Nextcloud,而是检查一下$work/app/config/config.php
文件的内容。这是一个示例。
- Redis缓存信息:
'memcache.local' => '\\OC\\Memcache\\APCu', // 默认是APCu。好像没法改为Redis?
'memcache.distributed' => '\\OC\\Memcache\\Redis',
'memcache.locking' => '\\OC\\Memcache\\Redis',
'redis' =>
array (
'host' => 'cache', // 和docker-compose.yml中Redis的“小名”要一致。
'password' => '', // docker-compose.yml中没声明,故留空。
'port' => 6379,
),
- 域名限制性。如果使用的是https访问,可以这样写:
array (
0 => '192.168.1.123',
1 => 'nextcloudtest.hwb0307.com',
),
'overwritehost' => 'nextcloudtest.hwb0307.com:4443',
'overwriteprotocol' => 'https',
'overwrite.cli.url' => 'http://nextcloudtest.hwb0307.com:4443',
这里假定使用的443端口为4443
。如果你直接使用443,这个端口号可以不写。
如果仅在本地访问,可以这样写:
array (
0 => '192.168.1.123',
),
'overwritehost' => 'http://192.168.1.123:1234',
修改完成后,直接重启docker stack即可:
docker-compose restart
管理设置
看看管理设置的安全与后台有没有问题,有问题按《Docker系列 搭建个人云盘服务nextcloud》的“警告&Bug”小节。 不过,由于我们使用了Nginx作为Web服务器,一些bug的解决方法和之前的Apache服务器是不同的。具体情况具体分析喽!我暂时是没遇到太多问题:
小结
整个布署过程比Nextcloud-Apache稍复杂些。不过,如果你对Docker和Nextcloud比较熟悉,应该难度不大。如果你有一台强大的服务器,这个方案是很推荐的,可拓展性和性能都可以上一个档次!官方仓库的教程也十分贴心,有相见恨晚的感觉!其它使用技巧见学习地图的“Nextcloud”系列,这里不多说了。
以后有什么使用心得会继续更新内容。请拭目以待!
扩展阅读
- Slow uploads with HTTP/2 · Issue #9578 · nextcloud/documentation:关于Nextcloud上传速度慢的相关讨论。
---------------
完结,撒花!如果您点一下广告,可以养活苯苯😍😍😍
按照您的步骤,到:Dockerfile要求安装一个nginx容器nginx:alpine,pull了nginx:alpine镜像,直接启动安装容器即可吗?或者说这步具体应该怎么操作(是个菜鸟,一直没搞明白)。
做好准备工作,最后文件夹包含这些文件就行:
之后严格按照教程的顺序来走即可。
再请教:部署成功后,通过npm反代,用苹果手机的app登录出错,无法登录。还需要设置哪里吗?
debian12最新版,apt upgrade更新时速度太慢,只有15K左右的速率,更换了国内的阿里等源,仍然从deb.debian.org更新文件,速度太慢。有什么办法解决吗?
如果你是指build镜像的过程,你可以了解一下docker build image时镜像源是不是可以选。 我暂时没研究过这个问题 (ฅ´ω`ฅ)
先用 apache 镜像部署的,性能实在太拉,直接切换 fpm 镜像部署,没遇到问题(没有切换域名,仅更换了镜像)
确实,Apache只是简单,但性能是拉一点 ~ 总之我自己是越来越受不了Apache那一套了,所以使用的Nginx 😔
大佬,家用nas部署是不是要配合frp内网穿透啊,我按照教程用ddns-go和npm反代之后外网环境还是没法访问
这可能会由很多原因造成。你家的宽带如果没有公网IP,则不能用ddns-go/NPM的体系来访问,只能用frp之类的内网穿透方案。
按照教程搭建 运行起来 访问502了⌇●﹏●⌇
方便的话可以远程帮你看一下。我加你QQ啦!
遇到下面的安全警告:
您的网页服务器未正确设置以解析“/.well-known/webfinger”
您的网页服务器未正确设置以解析“/.well-known/nodeinfo”
在Nginx Proxy Manager里面添加
location /.well-known/webfinger {
return 301 $scheme://$host:$server_port/index.php/.well-known/webfinger;
}
location /.well-known/nodeinfo {
return 301 $scheme://$host:$server_port/index.php/.well-known/nodeinfo;
}
如图:
![msedge_IMjrN49bl8]()

查看图片
。 而且,你没发现下面那位大佬,也有说到你的这个问题嘛! 我用的nginx.conf和官网的是不一样的。你仔细比较一下。 你可以直接复制我的使用,我也给出示例了
喔,我知道你的意思了,我之前也加了。 忘了说了! 谢谢提醒哈! 教程更新了。
文档写的很棒,很有参考性,谢谢分享。
实践时没仔细看文档www.conf缺了user和group的配置
直接配置了https,重定向的路径没有给全,nextcloud安全性检查难以通过。
就碰到这两问题,浪费了点时间。
文档写的很详细,再次感谢
谢谢提醒! “重定向的路径没有给全,nextcloud安全性检查难以通过”是指什么,可否讲得详细些?
可能是在修改config.php时,没有添加’overwritehost’ 和’overwriteprotocol’ ,
nextcloud安全性检查时carddav、caldav、webfinger、nodeinfo没有能通过,最后直接修改了nginx.conf配置
location = /.well-known/carddav { return 301 https://domain.com:8080/remote.php/dav/; }
location = /.well-known/caldav { return 301 https://domain.com:8080/remote.php/dav/; }
location =/.well-known/webfinger {return 301 https://domain.com:8080/index.php/.well-known/webfinger;}
location =/.well-known/nodeinfo {return 301 https://domain.com:8080/index.php/.well-known/nodeinfo;}
噢噢,这些点我之前都有讲过。 成功就行,这个版本还是不错的! 另外,如果你使用Onlyoffice的话,尽量不要使用它的预览功能,否则进入一个多文档文件夹时可能会拖慢甚至是卡死nextcloud。 之后还有什么经验也欢迎分享哈!
谢谢提醒
我的nextcloud主要是给Obsidian和Typora多机同步用的,nextcloud本身使用率不高,一直感觉nextcloud太臃肿。
对于不确定怎么移植数据的我,不太敢换新玩意。
嗯嗯,总之是一个方案。 你可以开个测试容器体验一下。迁移数据的方案我也没折腾成功,只能说将数据重新上传了。因为在nextcloud的根目录下,文件目录格式是保持的,所以直接拉取上传也挺方便。 当时我就10来个G的数据(主要是手机相册),上传很快。
搭好容器,然后文件夹形式重新上传文件。可是系统配置,如分享链接等不就得重新配置了么。
是啊 当时NAS的没有多少分享链接,所以直接重建。 分享比较多的就挺难受的。 以后折腾一下看看有没有万全之策,哎!
我现在用思源笔记+nextcloud配合使用。
笔记中我可以直接贴nextcloud的内链,如https://****/f/746。很方便文件管理
对应的就是,直接上新容器这些内链肯定会变化。
也不失为一种可考虑的方案。 以后有机会研究 (ฅ´ω`ฅ)