背景
本文记录的是国庆节期间在家做的一个研究和探索的过程,之所以没有提 CloudDrive
,是老苏最终想实现的是一个通用的 WebDAV
客户端,而不仅仅是挂载阿里云盘。
关于
CloudDrive
可以看老苏之前写的 『 适合国内网盘的免费挂载工具CloudDrive 』
提出问题
老苏的无损音乐放在了阿里云盘,阿里云盘又通过 Docker
支持了 WebDAV
,现在的问题是怎么挂载到群晖,使之成为一个能被 Airsonic
等流媒体软件直接使用的音乐库?
关于阿里云盘支持
WebDAV
,可以看老苏之前写的
一开始老苏选择了 远程连接
选择 WebDAV
因为没设置 WebDAV
账号、密码,所以只需要填 IP
和端口
应用之后就可以像访问群晖的本地盘一样使用了
但是老苏发现这种方式不能被 docker
识别,因为在 添加文件夹
中找不到我们刚才挂载成功的 WebDAV
目录
解决方案
老苏找到了 davfs2
,这是一个 Linux
文件系统驱动程序,允许您把 WebDAV
资源挂载到您的 Linux
文件系统中,就像它们是本地磁盘一样。但是唯一的问题是需要下源代码自己编译,这对大部分人来说还是比较麻烦的。
当然也有现成的 WebDAV Client
,比如 efrecon/webdav-client
。
老苏抱着折(学习)腾(研究)的目的,还是想自己尝试基于 davfs2
构建一个 docker
版的 WebDAV Client
。
构建镜像
如果你不想自己构建,可以跳过,直接阅读下一章节
老苏参考了很多的案例,形成了最终的 Dockerfile
,有两个特点记录一下
- 采用了
tini
做进程管理 - 采用了死循环来防止脚本退出
FROM ubuntu:16.04
MAINTAINER laosu<[email protected]>
RUN apt-get update
&& apt-get install -y davfs2
&& mkdir -p /mnt/webdrive
&& apt-get clean
&& rm -rf /tmp/* /var/lib/apt/lists/* /var/tmp/*
VOLUME /mnt/webdrive
COPY ./start.sh /usr/local/bin
RUN chmod +x /usr/local/bin/start.sh
# Add Tini
ENV TINI_VERSION v0.19.0
# ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
ADD https://hub.fastgit.org/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
RUN chmod +x /tini
ENTRYPOINT ["/tini", "--"]
# Run your program under Tini
CMD [ "/usr/local/bin/start.sh" ]
下面是 start.sh
文件,最后增加了一个死循环,目的是不要让这个脚本退出,否则拉起的进程也退出了
#!/bin/bash
# Set defaults
USER=${
WEBDRIVE_USER}
PASSWORD=${
WEBDRIVE_PASSWORD}
URL=${
WEBDRIVE_URL}
FOLDER_USER=${
PUID:-0}
echo "$URL $USER $PASSWORD" >> /etc/davfs2/secrets
# Create user
if [ $FOLDER_USER -gt 0 ]; then
useradd webdrive -u $FOLDER_USER -N -G users
fi
# Mount the webdav drive
echo "--Mount begin--"
mount -t davfs $URL /mnt/webdrive -o uid=$FOLDER_USER,gid=users,dir_mode=755,file_mode=755
echo "--Mount end--"
# Just keep this script running
while [[ true ]]; do
sleep 1
echo "--loop--"
done
构建镜像和容器运行的基本命令如下
# 将 Dockerfile 和 start.sh 放在同一个目录
# 构建镜像
docker build -t wbsu2003/webdav-client:v1 .
# 生成容器
docker run -d
--name webdav-client
--privileged
--cap-add=SYS_ADMIN
--device /dev/fuse
-e WEBDRIVE_USER=<username>
-e WEBDRIVE_PASSWORD=<password>
-e WEBDRIVE_URL=http://url/webdav/
-e PUID=1000
-v <host/path/to/folder>:/mnt/webdrive:shared
wbsu2003/webdav-client:v1
举个栗子,下面是直接在编译 Docker
的 CentOS
上挂载 webdav-aliyundriver
映射的阿里云盘
# 创建共享挂载点
mount --bind /mnt /mnt
mount --make-shared /mnt
docker run -d
--name webdav-client
--privileged
--device /dev/fuse
-e WEBDRIVE_USER=admin
-e WEBDRIVE_PASSWORD=123456
-e WEBDRIVE_URL=http://192.168.0.199:8123/
-e PUID=1000
-v /mnt/webdav:/mnt/webdrive:shared
wbsu2003/webdav-client
群晖验证
安装方法和 RcloneBrowser
比较类似,如果你还不了解,可以看看老苏之前写的 『 群晖上通过RcloneBrowser挂载云盘 』
第一步、建目录
在 docker
文件夹中,创建一个新文件夹,并将其命名为 webdav
第二步、共享挂载
如果你已经安装过
RcloneBrowser
,这一步可以跳过
因为老苏映射的目录在 volume1
上,如果你的目录是其他的卷上,记得修改
# 共享挂载
mount --make-shared /volume1
不然后面 mount
的时候可能会遇到下面这样的错误
docker: Error response from daemon: linux mounts: path /volume1/docker/webdav is mounted on /volume1 but it is not a shared mount.
这条命令在群晖重启后需要重新执行,所以我们可以把这句命令,通过 任务计划
加到开机脚本中
这是一个触发任务,事件是开机
邮件发不发看个人需要,主要是运行脚本
第三步、启动容器
在 ssh
客户端中执行下面的命令即可
除了挂载的卷,其他跟在
CentOS
上是一模一样的
docker run -d
--name webdav-client
--privileged
--device /dev/fuse
-e WEBDRIVE_USER=admin
-e WEBDRIVE_PASSWORD=123456
-e WEBDRIVE_URL=http://192.168.0.199:8123/
-e PUID=1000
-v /volume1/docker/webdav:/mnt/webdrive:shared
wbsu2003/webdav-client
容器运行成功后,在 FileStation
中查看,已经获取到了云盘的目录
可以像本地资源一样使用,现在来试试 Airsonic
开始扫描,记得勾选 快速模式
但是播放就不行了,就算是预览个图片感觉都很慢,可能跟 WebDAV
的机制有关系,反正对老苏来说没有什么实际意义
遗留问题
- 和
RcloneBrowser
、CloudDrive
一样,在复制的时候也会报错,看来基于容器的fuse
映射在群晖的FileStation
上是无解的
-
不支持密码和账号为空的
WebDAV
挂载,返回错误/sbin/mount.davfs:/etc/davfs2/secrets:69: malformed line
,但是因为问题1
的缘故,老苏已经不想再继续下去 -
虽然没测坚果云,但老苏知道肯定不行,因为坚果云的
WebDAV
服务器不支持Class 1
,需要在davfs2.conf
中改为ignore_dav_header 1
,老苏压根没做处理
小结
如果你需要一个通用的 WebDAV Client
,建议去试试 efrecon/webdav-client
,比老苏写的严谨,在容器停止的时候,做了 unmount
处理,规避了很多问题,比如导致 FileStation
不能列出文件
# 生成容器
docker run -it --rm
--device /dev/fuse
--cap-add SYS_ADMIN
--security-opt "apparmor=unconfined"
--env "WEBDRIVE_USERNAME=<YourUserName>"
--env "WEBDRIVE_PASSWORD=<SuperSecretPassword>"
--env "WEBDRIVE_URL=https://dav.box.com/dav"
--env "DAVFS2_ASK_AUTH=0"
-v /mnt/tmp:/mnt/webdrive:rshared
efrecon/webdav-client
不过都是基于同样的技术实现的,所以遗留 问题 1
也同样存在,速度各方面也没太大的差异
虽然不算达成了目标,但是在折腾的过程中还是学到了很多东西
参考文档
volga629/davfs2: davfs2 is a Linux tool for connecting to WebDAV shares as though they were local disks.
地址:https://github.com/volga629/davfs2
davfs2.conf: Configuration file for mount.davfs – Linux Man Pages (5)
地址:https://www.systutorials.com/docs/linux/man/5-davfs2.conf/
如何在一个Docker中同时运行多个程序进程?_dianfu2892的博客-程序员宅基地 – 程序员宅基地
地址:https://www.cxyzjd.com/article/dianfu2892/101466594
richardregeer/docker-davfs-webdisk: Use docker to mount a davfs webdisk
地址:https://github.com/richardregeer/docker-davfs-webdisk
efrecon/docker-webdav-client: WebDAV client for Docker with easy access to all davfs2 options!
地址:https://github.com/efrecon/docker-webdav-client