更新1:在调试中发现发现 Windows Docker 和 MySQL for Windows 之间的互访有严重的问题,目前改用Docker容器构建MariaDB数据库,所有功能一切正常。修改一些过于啰嗦的描述。运行环境有改动。

环境:

物理主机系统: Windows server 2019 Datecenter (v1809, 17763.805)
Docker: Docker for windows 2.2.0.4 build 43472(Engine: 19.03.8, Compose: 1.25.4)
Mariadb: Docker (mariadb:latest)
Nginx: Docker (nginx:latest)
Nextcloud: 18.0.2 (hub.docker.com/_/nextcloud, nextcloud:latest, nextcloud:apache, OS:Linux/amd64)
可选附加:
Onlyoffice-document-server:Docker (onlyoffice/documentserver:latest)
redis:Docker (redis:latest)

前置工作

Nextcloud镜像的选择

在官方Docker页面中主要版本有默认的Apache版和采用容器化Nginx的FPM版,在我个人实际搭建过程中FPM版的Nginx和宿主机windows之间隔着一层NAT,配置调试起来显得十分麻烦,故选择运行起来更简单的Apache版

容器间互访

将每个容器的网络加入同一外部Host网络就可以实现容器间通过service name互访

networks:
  default:
    external:
      name: shared
Docker for windows

安装是全自动创建Docker Host的Hyper-V虚拟机

创建共用网络 (关键)

docker network create shared

这是后续MariaDB+NextCloud+Nginx互访工作的关键步骤

MariaDB
MariaDB.yml
version: "3"

services:

  mariadb:
    image: mariadb:latest
    container_name: mariadb
    command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --innodb-flush-method=fsync
    environment:
      - TZ=Asia/Shanghai
      - MYSQL_ROOT_PASSWORD=password  # 必须, root账户的密码
      - MYSQL_LOG_CONSOLE=true
    volumes:
      # 挂载数据存储路径,建议外置数据
      - /C/Docker/mariadb:/var/lib/mysql
      # 挂载外置MariaDB配置文件
      - /C/Docker/mariadb-conf/my.cnf:/etc/my.cnf
    restart: unless-stopped
    networks:
      - default

  # 一起搭建方便通过Web操作数据库
  phpmyadmin:
    image: phpmyadmin/phpmyadmin:4.9.4
    container_name: phpmyadmin
    environment:
      - TZ=Asia/Shanghai
      # 允许访问不同数据库
      - PMA_ARBITRARY=1
      # 默认访问上面的mariadb
      - PMA_HOST=mariadb
    restart: unless-stopped
    expose:
      - '80'
    ports:
      # 映射端口
      - 8080:80
    networks:
      - default

networks:
  default:
    external:
      name: shared
部署数据库

通过docker exec -it mariadb bash进入容器内部使用命令操作数据库

#登入数据库
mysql -u root -p

创建环境

# 创建数据库nextcloud
create database nextcloud;
# 创建用户nextcloud
create user nextclouduser@% identified by 'password';
# 给nextcloud用户赋予数据库nextcloud所有权限
grant all privileges on nextcloud.* to nextcloud@% identified by 'password';
# 重载刷新权限
flush privileges;

主体搭建部署

NextCloud
NextCloud.yml
version: '3'

services:

  redis:
    image: redis
    container_name: nextcloud-redis
    restart: unless-stopped
    networks:
      - default
    expose:
      - '6379'

  nextcloud:
    image: nextcloud
    container_name: nextcloud
    restart: unless-stopped
    depends_on:
      - redis
    environment:
      - TZ=Asia/Shanghai
    volumes:
      - /C/Docker/nextcloud:/var/www/html                    # NextCloud主程序存储路径
      - /D/Docker/nextcloud/data:/var/www/html/data            # NextCloud数据存储路径
    expose:
      - '80'                                            # 暴露80端口供Nginx反向代理用
    ports:
      - 8080:80                                            # 转发8080端口至80端口
    networks:
      - default

networks:
  default:
    external:
      name: shared

主程序挂载到外部是方便在Windows上修改程序配置以及保持程序与数据操作权限统一,但这样在NextCloud程序更新效率和运行效率上会打一点折扣,还会破坏镜像自身内置默认的以www-data运行的crontab,需要外部Windows配置计划任务运行cron.php

如果主程序路径选择volume挂载到Windows系统路径,那么在Docker容器中运行的Nextcloud默认以root用户权限运行,所以在访问时会提示设置权限chmod 0770,无论是chown还是chmod都无法解决,可通过强行忽略文件权限检查解决

忽略数据目录权限检查

在/var/www/html/config/config.php中加入以下内容

#检查数据目录权限  
'check_data_directory_permissions' => false,
添加可信任访问域名

在/var/www/html/config/config.php添加Trusted_Domains,不然Nextcloud的Web端无法访问

  'trusted_domains' => 
  array (
    0 => 'example.com',
    1 -> 'localhost',
  ),

NextCloud初步搭建完成,通过 http://localhost:80http://localhost:8080 访问NextCloud的Web界面进行初始化操作

数据库用户名: nextcloud
数据库用户密码: password
数据库名: nextcloud
数据库Host: mariadb
Nginx (HTTPS访问)
Nginx.yml
version: "3"

services:

  nginx:
    image: nginx:latest
    container_name: nginx
    volumes:
      - /C/Docker/nginx/nginx.conf:/etc/nginx/nginx.conf    # 外置Nginx配置文件
      - /C/Docker/nginx/conf:/etc/nginx/conf.d                # 外置Nginx配置文件
    restart: unless-stopped
    ports:
      - 8081:443                                # 转发10006端口至Nginx监听的443端口
    networks:
      - default

networks:
  default:
    external:
      name: shared
NextCloud.conf
server {

    #Nginx监听端口
    listen      443 ssl;
    #域名, IP, 本地地址都可以填写
    server_name nc.example.com;

    # SSL证书路径
    ssl_certificate       /etc/ssl/cert.cer;
    # SSL私钥路径
    ssl_certificate_key   /etc/ssl/private.key;
    ssl_protocols SSLv2 SSLv3 TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
    ssl_prefer_server_ciphers on;

    #以下部分为隐藏header, 为了解决nextcloud自检问题
    proxy_hide_header X-Content-Type-Options;
    proxy_hide_header X-Download-Options;
    proxy_hide_header X-Frame-Options;
    proxy_hide_header X-Permitted-Cross-Domain-Policies;
    proxy_hide_header X-Robots-Tag;

    add_header Strict-Transport-Security "max-age=15552000; includeSubDomains; preload" always;
    add_header Referrer-Policy "no-referrer";
    add_header X-Content-Type-Options nosniff;
    add_header X-Download-Options "noopen";
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Permitted-Cross-Domain-Policies "none";
    add_header X-Robots-Tag "none";
    add_header X-XSS-Protection "1; mode=block";

    client_max_body_size 10G;
    fastcgi_buffers 64 4K;
    fastcgi_hide_header X-Powered-By;
  
    # 反向代理, 通过service name访问
    location / {
        proxy_pass http://nextcloud:80/;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_buffer_size 64k;
        proxy_buffers 8 64k;
        proxy_busy_buffers_size 64k;
        proxy_temp_file_write_size 64k;
    }

    location = /.well-known/host-meta {
      return 301 $scheme://$http_hostpublic.php?service=host-meta;
    }

    location = /.well-known/host-meta.json {
      return 301 $scheme://$http_host/public.php?service=host-meta-json;
    }

    #解决自检carddav未正常配置解析提示问题 
    location = /.well-known/carddav {
        return 301 $scheme://$http_host/remote.php/dav;
    }

    #解决自检carddav未正常配置解析提示问题
    location = /.well-known/caldav {
        return 301 $scheme://$http_host/remote.php/dav;
    }

    #解决自检webfinger未正常配置解析提示问题
    location = /.well-known/webfinger{
        return 301 $scheme://$http_host/index.php/.well-known/webfinger;
    }

    #解决自检nodeinfo未正常配置解析提示问题
    location = /.well-known/nodeinfo{
        return 301 $scheme://$http_host/index.php/.well-known/nodeinfo;
    }

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ {
        deny all;
    }

    location ~ ^\/(?:\.|autotest|occ|issue|indie|db_|console) {
        deny all;
    }

}

Nextcloud在实际使用中经常出现访问超时,原因是Nextcloud:latest用Apache作为网页服务器监听HTTP 80端口,在Nginx反代中可能无法侦测正确的协议,需要添加参数强行覆写

在NextCloud程序目录的config/config.php中添加以下内容

  'overwriteprotocol' => 'https',

至此,NextCloud在公网可通过 https://example.com:8081/ 访问

可选部分

Onlyoffice-document-server

Nextcloud官方提供连接onlyoffice服务的应用,与onlyoffice对接后能实现在NextCloud内直接Web访问打开并编辑office文档 (pptx, xlsx, docs等),通过Docker可以一键配置

version: '3'

services:
  onlyoffice-document-server:
    container_name: onlyoffice-document-server
    image: onlyoffice/documentserver:latest
    stdin_open: true
    restart: unless-stopped
    environment:
      - TZ=Asia/Shanghai
      # 启用HTTPS HSTS
      - ONLYOFFICE_HTTPS_HSTS_ENABLED=true
      # SSL证书路径
      - SSL_CERTIFICATE_PATH=/var/www/onlyoffice/Data/certs/cert.cer
      # SSL私钥路径
      - SSL_KEY_PATH=/var/www/onlyoffice/Data/certs/private.key
      - REDIS_SERVER_HOST=onlyoffice-redis
      - REDIS_SERVER_PORT=6379
    deploy:
      resources:
        limits:
          cpus: '0.50'
          memory: 2048M
    volumes:
      # 外置log
      - /D/Docker/onlyoffice/DocumentServer/logs:/var/log/onlyoffice
      # 外置data
      - /D/Docker/onlyoffice/DocumentServer/data:/var/www/onlyoffice/Data
      # 挂载SSL证书和私钥路径
      - /C/SSL-Certificates:/var/www/onlyoffice/Data/certs
      # 外置lib
      - /D/Docker/onlyoffice/DocumentServer/lib:/var/lib/onlyoffice
    ports:
      - 8082:443
    depends_on:
      - onlyoffice-redis
    networks:
      - default

  onlyoffice-redis:
    container_name: onlyoffice-redis
    image: redis:latest
    restart: unless-stopped
    networks:
      - default
    expose:
      - '6379'

networks:
  default:
    external:
      name: shared
证书安装
  1. 在/var/www/onlyoffice/Data中建立 "certs" 文件夹,将SSL证书 (cert.cer) 和私钥 (private.key)放入
  2. 修改environment环境参数挂载路径中的文件名称
environment:
 - SSL_CERTIFICATE_PATH=证书路径
 - SSL_KEY_PATH=私钥路径

通过访问https://example.com:8082/ ,可以查看Document Server运行状况,显示 "Document Server is running" 表示成功

最后在Nextcloud的Onlyoffice连接应用中设置Document Editing Service address为https://example.com:8082/

页面下方出现settings一系列选项则表示已成功连接

Redis

Nextcloud官方推荐使用Redis缓存Nextcloud,在上述NextCloud部分已经默认一同部署

邮件提醒

NextCloud可以使用现有的邮箱服务、用户发送提醒邮件,在网页界面—设置—基本设置—电子邮件服务器中配置

结语

主要优点:

  • 提供了丰富的扩展可供安装
  • 文件完整地存储在服务器上,方便直接复制备份

主要缺点:

  • 基于PHP,运行效率有折扣
最后修改:2022 年 10 月 12 日
个人分享,随意打赏