在树莓派上搭建完全Docker化的NextCloud个人云盘

其实这个教程完全可以用在任何适合的ARM设备上,当然X86_64也只需要稍微修改一下配置文件就可以了(Docker真的好用),本文假设你正在用Debian或者基于它的发行版(比如树莓派的Raspbian),其他的应该也差不多吧233。

这篇文章将会以树莓派(Raspbian)为例介绍如何利用Docker跑一个NextCloud,并且配置Let’s Encrypt和DDNS来实现HTTPS访问。

准备

首先我们需要安装Docker以及Docker Compose,直接用官方给的script就好。Docker Compose是一个用来定义和运行多个Docker程序的工具,可以用它来管理多个容器而不需要shell脚本。

curl -fsSL 'https://get.docker.com' -o get-docker.sh
sudo sh get-docker.sh

sudo apt install docker-compose
sudo usermod -aG docker ${USER} #将用户添加到Docker组里面

注销然后重新登录来使它生效。然后确认一下Docker有没有正确安装:

sudo docker run hello-world

如果正确输出了hello world,那么就可以进行下一步啦。

服务搭建

Traefik反向代理

Træfɪk 是一个为了让部署微服务更加便捷而诞生的现代HTTP反向代理、负载均衡工具。 它支持多种后台 (Docker, Swarm, Kubernetes, Marathon, Mesos, Consul, Etcd, Zookeeper, BoltDB, Rest API, file…) 来自动化、动态的应用它的配置文件设置。

它和Docker集成得比较好,所以我们在这里用Traefik而不用NGINX或者Apache,我感觉太麻烦了。

我们需要这样一些服务:

  • Traefik: 反向代理和它自带的Web UI
  • Nextcloud: 个人云盘服务
  • MariaDB: 数据库, MySQL的分支
  • DDClient: 动态DNS(非必须)

接下来我们就着手开始构建服务框架了,新建一个文件夹并且给予适当的权限:

mkdir ~/docker
chmod -R 775 ~/docker

Docker环境变量配置

我们需要一个.env的环境变量文件,不过在开始之前我们需要执行id命令来记下PUID(也就是uid)和PGID(gid):

id

然后编辑.env文件:

cd ~/docker
touch .env
vim .env

你的.env文件应该和这个差不多:

PUID=your_uid
PGID=your_gid
TZ=Asia/Shanghai
USERDIR=/home/pi
MYSQL_ROOT_PASSWORD=your_mysql_rootpassword_here
MYSQL_DATABASE=nextcloud
MYSQL_USER=nextcloud
MYSQL_PASSWORD=your_password_here
DOMAINNAME=your_domain.com
CLOUDFLARE_EMAIL=example@domain.com
CLOUDFLARE_API_KEY=your_cloudflare_api_key

因为我用的是Cloudflare的DNS服务,所以以下也会以Cloudflare为例,其他DNS提供商可以参考Traefik的官方文档来进行配置。

Traefik配置文件

给它整一个文件夹吧,我们需要创建一个空的acme.json文件来给Docker容器调用,同时也需要设置正确的权限。

mkdir ~/docker/traefik
mkdir ~/docker/traefik/acme

touch ~/docker/traefik/acme/acme.json
chmod 600 ~/docker/traefik/acme/acme.json

然后创建和编辑traefik.toml文件:

touch ~/docker/traefik/traefik.toml
vim ~/docker/traefik/traefik.toml

这是traefik.toml:

#debug = true
logLevel = "WARN" #DEBUG, INFO, WARN, ERROR, FATAL, PANIC
InsecureSkipVerify = true
defaultEntryPoints = ["https", "http"]

# Traefik的Web界面
[web]
address = ":8080"

# 强制 HTTPS
[entryPoints]
  [entryPoints.http]
  address = ":80"
    [entryPoints.http.redirect]
    entryPoint = "https"
  [entryPoints.https]
  address = ":443"
    [entryPoints.https.tls]

# Let's encrypt 配置
[acme]
email = "sample@domain.com"
storage="/etc/traefik/acme/acme.json"
entryPoint = "https"
acmeLogging=true
onDemand = false #在容器被创建的时候获取证书
caServer = "https://acme-v02.api.letsencrypt.org/directory"
[acme.dnsChallenge]
  provider = "cloudflare"
  delayBeforeCheck = 90
[[acme.domains]]
   main = "*.your_domain.com"
   sans = ['your_domain.com']


# 与Docker主机的连接
[docker]
endpoint = "unix:///var/run/docker.sock"
domain = "your_domain.com"
watch = true
# This will hide all docker containers that don't have explicitly
# set label to "enable"
exposedbydefault = false

关于Traefik的配置文件可以参考官方文档,他们提供了很详细的说明

DDClient配置文件

(如果你不需要动态DNS解析的话,这里和下面有关DDClient都可以忽略)

这里建议在官方的示例文件上改,不然太多了

mkdir ~/docker/ddclient
wget 'https://raw.githubusercontent.com/ddclient/ddclient/master/sample-etc_ddclient.conf' -O ~/docker/ddclient/ddclient.conf

vim ~/docker/ddclient/ddclient.conf

差不多要改的地方是这些:

use=web  #把这行注释去掉就行

##
## CloudFlare (www.cloudflare.com)
##
protocol=cloudflare,        \
zone=your_domain.com,            \
ttl=1,                      \
login=sample@domain.com,     \
password=your_api_key_here             \
your_domain.com,www.your_domain.com,
subdomain1.yout_domain.com, subdomain2.your_domain.com

你可以看它的注释,写得很清楚

Docker代理网络

我们的服务需要一个内部Docker网络(default)和外部的Docker网络(traefik_proxy)以供Traefik使用

docker network create traefik_proxy

Docker Compose 文件

在这里我们将配置所有的服务,首先创建文件:

touch ~/docker/docker-compose.yml
vim ~/docker/docker-compose.yml

docker-compose是这样的:

version: "2"
services:
    traefik:
        hostname: traefik
        image: traefik:latest
        container_name: traefik
        restart: always
        domainname: ${DOMAINNAME}
        networks:
          - default
          - traefik_proxy
        ports:
          - "80:80"
          - "443:443"
          - "8080:8080"
        environment:
          - CLOUDFLARE_EMAIL=${CLOUDFLARE_EMAIL}
          - CLOUDFLARE_API_KEY=${CLOUDFLARE_API_KEY}
        labels:
          - "traefik.enable=true"
          - "traefik.backend=traefik"
          - "traefik.frontend.rule=Host:traefik.${DOMAINNAME}"
          - "traefik.port=8080"
          - "traefik.docker.network=traefik_proxy"
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock:ro
          - ${USERDIR}/docker/traefik:/etc/traefik
          - ${USERDIR}/docker/shared:/shared

    nextcloud:
      container_name: nextcloud
      restart: always
      image: nextcloud:latest
      links:
        - mariadb
      volumes:
        - /mnt/nextcloud:/var/www/html
        # 如果要将文件数据存在外部,那么这里应该加一条
        # - /path/to/your/data:/var/www/html/data
      environment:
        - PUID=${PUID}
        - PGID=${PGID}
        - TZ=${TZ}
      networks:
        - traefik_proxy
        - default
      labels:
        - "traefik.enable=true"
        - "traefik.backend=nextcloud"
        - "traefik.frontend.rule=Host:nextcloud.${DOMAINNAME}"
        - "traefik.docker.network=traefik_proxy"
        - "traefik.port=80"

    mariadb:
       image: hypriot/rpi-mysql:latest #这里要用树莓派armhf架构的
       container_name: "mariadb"
       hostname: mariadb
       volumes:
           - ${USERDIR}/docker/mariadb:/var/lib/mysql
       ports:
         - 3306:3306
       restart: always
       environment:
         - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
         - MYSQL_DATABASE=${MYSQL_DATABASE}
         - MYSQL_USER=${MYSQL_USER}
         - MYSQL_PASSWORD=${MYSQL_PASSWORD}
         - PUID=${PUID}
         - PGID=${PGID}
         - TZ=${TZ}

    ddclient:
        image: linuxserver/ddclient:arm32v7-latest
        container_name: "ddclient"
        restart: always
        environment:
          - PUID=${PUID}
          - PGID=${PGID}
          - TZ=${TZ}
        volumes:
          - ${USERDIR}/docker/ddclient:/config

networks:
  traefik_proxy:
    external:
      name: traefik_proxy
  default:
    driver: bridge

启动服务!

启动Docker

docker-compose -f ~/docker/docker-compose.yml up -d

第一次运行会花一点时间,因为Docker会自动下载需要的镜像,Traefik会自动生成Let’s Encrypt证书并保存在acme.json里面。当然你也需要在路由器上正确设置端口转发(80和443以及其他需要的)到树莓派上。

参数-d表示在后台运行。

配置NextCloud

上述Docker服务启动完成后,打开 https://IP_ADDRESS 即可看见NextCloud的安装页面,用户名和密码填写好,下边数据目录选择/var/www/html/data(如果刚才docker-compose里面写了外部目录,这里依然填写这个),数据库选择MySQL/MariaDB,数据库用户名填nextcloud,密码是之前.env文件里的MYSQL_PASSWORD的值,数据库名填nextcloud,地址填mariadb

准备就绪后点击安装完成,稍等一会儿后就能进入NextCloud主页啦!

维护

以下内容都假设当前在~/docker目录下操作

日志

查看全部服务的日志

docker-compose logs

查看某一个服务的日志,或者要找什么关键词

docker-compose logs | grep SERVICE_NAME

关闭和重启

如果想一口气关闭全部,那么只需要:

docker-compose down

如果只想关闭某个特定的容器,就:

docker-compose stop CONTAINER_NAME

重启某个容器:

docker-compose restart CONTAINER_NAME

因为docker-compose up会自动检查镜像是否有更新,所以更新和重启都可以用这个命令:

docker-compose down && docker-compose up

后续和拓展阅读

不满足的话你还可以添加其他的服务,比如Home Assistant、GitLab什么的,都可以直接在docker-compose.yml里加,很方便的。以下是一些文档的地址,上面不懂的可以在官方文档里找答案。以及因为我是搭起来之后才写的文章,全靠回忆,所以有什么错误请指出,我会尽快改正:D

Traefik:https://docs.traefik.io/

NextCloud: https://docs.nextcloud.com/

Docker: https://docs.docker.com/

Docker Hub: https://hub.docker.com/

本页面的全部内容在 CC BY-NC-SA 4.0 协议之条款下提供,附加条款亦可能应用
本文链接:https://www.copperion.com/2019/raspberry-nextcloud-with-docker/