Nextcloud 的部署方式有很多种,经过折腾,发现了一种比较好的部署方式,我称之为混合部署。
在 QNAP 威联通 QTS 里部署 Nextcloud 的方式一般有以下几种:
- 常规的 LAMP 部署
- 通过 CLI 脚本部署
- QNAP qpkg 文件部署
- 通过 all-in-one Docker 部署
- 使用 QNAP 自带 Apache 部署
我使用过 3 种部署方式,
- 系统自带 Apache + Nextcloud 源码
- all-in-one Docker 部署
- 混合部署:公共 php-fpm + Nextcloud 源码
前两个我就简单介绍下,不做过多展开。
第三个会详细介绍一下。
以下环境均为 QNAP 威联通的 NAS 系统。其他系统路径可能需要自行调整。
系统自带的 Apache 部署
之前我一直用 QNAP 自带的 Apache 来安装 Nextcloud,通过 域名+Nextcloud端口号 的方式来访问。
但是后来随着服务越来越多,我使用 Nginx Proxy Manager 来统一进行反代,使用 二级域名+固定端口 的方式来访问各种服务,比较快捷方便。这时在配置 Apache + Nextcloud 反代时,搞了半天也没搞好。
另外系统自带的 Apache 版本较低,无法安装最新的 Nextcloud。而 Nextcloud 的大版本更新,还往往伴随着 break change,我有些担心一直不升级落后太多,等到想升级时会很麻烦或者造成一些数据损坏。
优点:效率高
缺点:
- 配置比较麻烦(如果不用 Nginx 进行反代的话倒是简单,但是那样访问起来不够”优雅”)
- 自带的 php 版本较低,Nextcloud 高版本对 php 版本有要求
All-in-ONE Docker 部署
很多人非常喜欢用官方 all-in-one docker 的安装方式,感觉轻松快捷,但是这个 all-in-one docker 我感觉开销是大了些
优点:部署简单,官方 docker 已经打包好了
缺点:如图中所示,链路较长,效率较低
对应的 docker-compose.yml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| --- version: "2" services: nextcloud: image: linuxserver/nextcloud:latest container_name: nextcloud environment: - TZ=Asia/Shanghai volumes: - /my_home/nextcloud/config:/config:rw - /my_home/nextcloud/data:/data:rw ports: - 2080:80 restart: always
|
混合部署:公用 php-fpm + Nextcloud
我目前在用的方式,已经稳定运行了半年了,更新起来毫无压力,管理界面上的检查也能全部 pass。
优点:效率高,php 版本、库包都在自己掌控中
缺点:php 需要自己编译镜像
相关配置如下:
编译 php-fpm 镜像的 Dockerfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| FROM php:8-fpm
RUN pecl install apcu && docker-php-ext-enable apcu
RUN CFLAGS="$PHP_CFLAGS" CPPFLAGS="$PHP_CPPFLAGS" LDFLAGS="$PHP_LDFLAGS" \ && apt-get update \ && apt-get install -y --no-install-recommends \ libmagickwand-dev \ && rm -rf /var/lib/apt/lists/* \ && pecl install imagick \ && docker-php-ext-enable imagick
RUN apt-get update && apt-get install -y --no-install-recommends \ vim \ && rm -rf /var/lib/apt/lists/*
RUN apt-get update && apt-get install -y --no-install-recommends \ libfreetype-dev \ libjpeg62-turbo-dev \ libpng-dev \ libwebp-dev \ libzip-dev \ libicu-dev \ libbz2-dev \ libgmp10 \ libgmp-dev \ && rm -rf /var/lib/apt/lists/* \ && docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp \ && docker-php-ext-configure intl \ && docker-php-ext-configure bcmath --enable-bcmath \ && docker-php-ext-configure gmp --with-gmp \ && docker-php-ext-configure sysvsem --enable-sysvsem \ && docker-php-ext-install -j$(nproc) gd zip pdo_mysql bz2 intl exif opcache sysvsem gmp bcmath
RUN { \ echo 'memory_limit=512M'; \ echo 'post_max_size=512M'; \ echo 'upload_max_filesize=512M'; \ } > /usr/local/etc/php/conf.d/docker-php-memlimit.ini;
RUN { \ echo 'apc.enable_cli=1'; \ } > /usr/local/etc/php/conf.d/apcu.ini;
RUN { \ echo 'opcache.memory_consumption=128'; \ echo 'opcache.interned_strings_buffer=8'; \ echo 'opcache.max_accelerated_files=4000'; \ echo 'opcache.revalidate_freq=2'; \ echo 'opcache.fast_shutdown=1'; \ } > /usr/local/etc/php/conf.d/opcache-recommended.ini
RUN { \ echo 'error_reporting = E_ERROR | E_WARNING | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_RECOVERABLE_ERROR'; \ echo 'display_errors = Off'; \ echo 'display_startup_errors = Off'; \ echo 'log_errors = On'; \ echo 'error_log = /dev/stderr'; \ echo 'log_errors_max_len = 1024'; \ echo 'ignore_repeated_errors = On'; \ echo 'ignore_repeated_source = Off'; \ echo 'html_errors = Off'; \ } > /usr/local/etc/php/conf.d/error-logging.ini
RUN echo 'alias ll="ls -la"' >> ~/.bashrc;
|
创建一个 network,便于 container 间的相互访问
1
| docker network create my-dockers-network
|
php-fpm 的一些配置 zz-docker.conf,下边启动 php-fpm 时会用
1 2 3 4 5 6 7 8 9 10
| [global] daemonize = no
[www] listen = 9000 pm = dynamic pm.max_children = 40 pm.start_servers = 15 pm.min_spare_servers = 15 pm.max_spare_servers = 25
|
php-fpm 的 docker-compose-php.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| version: '3.8' services: php: container_name: php-fpm image: php:8-fmp_zip_gd deploy: resources: limits: memory: 600M reservations: memory: 512M restart: always volumes: - /my_home/nginx-proxy-manager/php-config/zz-docker.conf:/usr/local/etc/php-fpm.d/zz-docker.conf - /my_home/nginx-proxy-manager/www:/var/www:rw - /my_home/nextcloud/data:/var/nextcloud:rw expose: - 9000 networks: - my-dockers-network
networks: my-dockers-network: external: true
|
php-fpm 启动后, docker exec -it php-fpm bash
进入容器,然后 chown 33:33 -R html
修改目录归属,否则 php-fmp 会报无权限写入 config
Nignx Proxy Manager(以下简称 NPM) 的 docker-compose.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| version: '3.8' services: nginx-proxy-manager: container_name: nginx-proxy-manager image: 'jc21/nginx-proxy-manager:latest' restart: always ports: - '8880:80' - '8881:81' - '8443:443' volumes: - /my_home/nginx-proxy-manager/data:/data - /my_home/nginx-proxy-manager/letsencrypt:/etc/letsencrypt - /my_home/nginx-proxy-manager/www:/var/www networks: - my-dockers-network
networks: my-dockers-network: external: true
|
在 NPM 的 /data/nginx/custom/http_top.conf
中添加:
1 2 3 4 5
| map $arg_v $asset_immutable { "" ""; default "immutable"; }
|
NPM 中配置对应的 Proxy Host(注意:不要开 Cache Assets)
还要在 Advanced 中进行如下配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
| root /var/www/html/nextcloud;
server_tokens off;
client_max_body_size 512M; client_body_timeout 300s; fastcgi_buffers 64 4K;
gzip on; gzip_vary on; gzip_comp_level 4; gzip_min_length 256; gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; gzip_types application/atom+xml text/javascript application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
client_body_buffer_size 512k;
add_header Referrer-Policy "no-referrer" always; add_header X-Content-Type-Options "nosniff" always; add_header X-Download-Options "noopen" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Permitted-Cross-Domain-Policies "none" always; add_header X-Robots-Tag "noindex, nofollow" always; add_header X-XSS-Protection "1; mode=block" always;
fastcgi_hide_header X-Powered-By;
index index.php index.html /index.php$request_uri;
location = /robots.txt { allow all; log_not_found off; access_log off; }
location = / { if ( $http_user_agent ~ ^DavClnt ) { return 302 $scheme://$http_host/remote.php/webdav/$is_args$args; } error_page 497 301 =307 https://$http_host$request_uri; }
location ^~ /.well-known { location = /.well-known/carddav { return 301 $scheme://$http_host/remote.php/dav/; } location = /.well-known/caldav { return 301 $scheme://$http_host/remote.php/dav/; }
location /.well-known/acme-challenge { try_files $uri $uri/ =404; } location /.well-known/pki-validation { try_files $uri $uri/ =404; } return 301 $scheme://$http_host/index.php$request_uri; }
location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; } location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { return 404; }
location ~ \.php(?:$|/) { rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+|.+\/richdocumentscode\/proxy) /index.php$request_uri;
fastcgi_split_path_info ^(.+?\.php)(/.*)$; set $path_info $fastcgi_path_info;
try_files $fastcgi_script_name =404;
include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $path_info; fastcgi_param HTTPS on;
fastcgi_param modHeadersAvailable true; fastcgi_param front_controller_active true; fastcgi_pass php-fpm:9000;
fastcgi_intercept_errors on; fastcgi_request_buffering off;
fastcgi_max_temp_file_size 0; }
location ~ \.(?:css|js|mjs|svg|gif|png|jpg|ico|wasm|tflite|map)$ { try_files $uri /index.php$request_uri; add_header Cache-Control "public, max-age=15778463, $asset_immutable"; access_log off;
location ~ \.wasm$ { default_type application/wasm; } }
location ~ \.woff2?$ { try_files $uri /index.php$request_uri; expires 7d; access_log off; }
location /remote { return 301 /remote.php$request_uri; }
location / { try_files $uri $uri/ /index.php$request_uri; }
|
在 /etc/config/crontab
里添加定时任务(以威联通 QTS 系统为例,其他系统自行调整)
1
| */5 * * * * /share/CACHEDEV1_DATA/.qpkg/container-station/bin/docker exec -u www-data php-fpm php /var/www/html/nextcloud/cron.php >/dev/null 2>&1
|
并使用 crontab /etc/config/crontab
生效
其中的 docker 路径可以通过 which docker
找到
客户端修改域名端口
在 server 端修改域名后,客户端只需修改配置文件里的域名即可,不用重新配置。
在对应系统下,先关闭 Nextcloud 程序,然后找到 cfg 文件修改 URL 即可。再启动 Nextcloud 后,会自动弹框要求登录授权,和之前那个账户一致,然后授权即可。
Linux: $HOME/.config/nextcloud/nextcloud.cfg
Windows: %APPDATA%\nextcloud\nextcloud.cfg
macOS: $HOME/Library/Preferences/nextcloud/nextcloud.cfg