Webdav:从搭建到放弃

最近发现常用的APP都加上了Webdav的备份选项,考虑到公网的webdav速度和成本,索性就用刚买的N1整一个临时的,用来备份APP。

Webdav简介

WebDAV 简介 WebDAV 是一组基于超文本传输协议的技术集合,有利于用户间协同编辑和管理存储在万维网服务器文档。 即 Web-based Distributed Authoring and Versioning (WebDAV),直译过来就是基于万维网的分布式创作和版本控制。

其实操作逻辑上类似RESTful,使用HTTP协议中规定的操作,完成对文件的增删改查等操作。

操作方案

自建云盘

比较有名的ownCloud,NextCloud等开源网盘项目是完全支持webdav协议的,但是这些应用依赖数据库,N1的内存就2G,更何况还想在上面跑点其他的应用,索性就pass了。

P.S. 自建云盘在大文件的操作上很可能使php进入崩溃状态,这也是我放弃自建云盘的原因。不过对于N1以上量级的板子可以考虑Seafile这样的解决方案,家庭场景下还是有着不错的性能。

webserver

常用的webserver都支持了webdav协议,但是我最习惯的Nginx对于部分指令的支持并不完善,还需要加入其他的模块,我想了想N1这个四核A53的编译速度,还是含泪放弃了(尤其是Nginx我都是apt安装的)

Caddy也支持http.webdav插件,配置起来非常友好,但是我不是Caddy党,对于Caddy目前还是观望状态。(Caddy2这个也没整明白)

Apache(httpd)倒是完全支持,但是对于N1来说确实用不到这个玩意,如果用Apache的话,后续的webserver配置学习成本太高(还是懒)

Docker

俗话说Docker一把梭就是干,但是遇到了问题,在Dockerhub上一番搜索之后,发现比较靠谱的image都是至少一年前更新的了,而且还是只build了amd64版本。

最终选择了bytemark/webdav进行改装。

docker官方提供了基于alpine的httpd镜像,但是不知道为什么bytemark/webdav没能自动同步构建。

梳理一下这个Dockerfile

FROM httpd:alpine

# These variables are inherited from the httpd:alpine image:
# ENV HTTPD_PREFIX /usr/local/apache2
# WORKDIR "$HTTPD_PREFIX"

# Copy in our configuration files.
COPY conf/ conf/

RUN set -ex; \
    # Create empty default DocumentRoot.
    mkdir -p "/var/www/html"; \
    # Create directories for Dav data and lock database.
    mkdir -p "/var/lib/dav/data"; \
    touch "/var/lib/dav/DavLock"; \
    chown -R www-data:www-data "/var/lib/dav"; \
    \
    # Enable DAV modules.
    for i in dav dav_fs; do \
        sed -i -e "/^#LoadModule ${i}_module.*/s/^#//" "conf/httpd.conf"; \
    done; \
    \
    # Make sure authentication modules are enabled.
    for i in authn_core authn_file authz_core authz_user auth_basic auth_digest; do \
        sed -i -e "/^#LoadModule ${i}_module.*/s/^#//" "conf/httpd.conf"; \
    done; \
    \
    # Make sure other modules are enabled.
    for i in alias headers mime setenvif; do \
        sed -i -e "/^#LoadModule ${i}_module.*/s/^#//" "conf/httpd.conf"; \
    done; \
    \
    # Run httpd as "www-data" (instead of "daemon").
    for i in User Group; do \
        sed -i -e "s|^$i .*|$i www-data|" "conf/httpd.conf"; \
    done; \
    \
    # Include enabled configs and sites.
    printf '%s\n' "Include conf/conf-enabled/*.conf" \
        >> "conf/httpd.conf"; \
    printf '%s\n' "Include conf/sites-enabled/*.conf" \
        >> "conf/httpd.conf"; \
    \
    # Enable dav and default site.
    mkdir -p "conf/conf-enabled"; \
    mkdir -p "conf/sites-enabled"; \
    ln -s ../conf-available/dav.conf "conf/conf-enabled"; \
    ln -s ../sites-available/default.conf "conf/sites-enabled"; \
    # Install openssl if we need to generate a self-signed certificate.
    apk add --no-cache openssl

COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
EXPOSE 80/tcp 443/tcp
ENTRYPOINT [ "docker-entrypoint.sh" ]
CMD [ "httpd-foreground" ]

在实际build的过程中,需要替换alpine的软件源(日常),并且遇到了(20019)DSO load failed: [client 127.0.0.1:43752] Could not open property database.这样的报错。排查出问题是来自于apr-util-dbm_db这个软件包。(这个软件包的描述是The Apache Portable Runtime Utility Library - Berkley DB driver),也就是说由于数据库驱动的缺失导致报错。

修改完成后的Dockerfile如下

FROM httpd:alpine

# These variables are inherited from the httpd:alpine image:
# ENV HTTPD_PREFIX /usr/local/apache2
# WORKDIR "$HTTPD_PREFIX"

# Copy in our configuration files.
COPY conf/ conf/

RUN set -ex; \
    # Replace repo with Aliyun
    sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories; \
    # Create empty default DocumentRoot.
    mkdir -p "/var/www/html"; \
    # Create directories for Dav data and lock database.
    mkdir -p "/var/lib/dav/data"; \
    touch "/var/lib/dav/DavLock"; \
    chown -R www-data:www-data "/var/lib/dav"; \
    \
    # Enable DAV modules.
    for i in dav dav_fs; do \
        sed -i -e "/^#LoadModule ${i}_module.*/s/^#//" "conf/httpd.conf"; \
    done; \
    \
    # Make sure authentication modules are enabled.
    for i in authn_core authn_file authz_core authz_user auth_basic auth_digest; do \
        sed -i -e "/^#LoadModule ${i}_module.*/s/^#//" "conf/httpd.conf"; \
    done; \
    \
    # Make sure other modules are enabled.
    for i in alias headers mime setenvif; do \
        sed -i -e "/^#LoadModule ${i}_module.*/s/^#//" "conf/httpd.conf"; \
    done; \
    \
    # Run httpd as "www-data" (instead of "daemon").
    for i in User Group; do \
        sed -i -e "s|^$i .*|$i www-data|" "conf/httpd.conf"; \
    done; \
    \
    # Include enabled configs and sites.
    printf '%s\n' "Include conf/conf-enabled/*.conf" \
        >> "conf/httpd.conf"; \
    printf '%s\n' "Include conf/sites-enabled/*.conf" \
        >> "conf/httpd.conf"; \
    \
    # Enable dav and default site.
    mkdir -p "conf/conf-enabled"; \
    mkdir -p "conf/sites-enabled"; \
    ln -s ../conf-available/dav.conf "conf/conf-enabled"; \
    ln -s ../sites-available/default.conf "conf/sites-enabled"; \
    # Install openssl if we need to generate a self-signed certificate.
    apk add --no-cache openssl apr-util apr-util-dbm_db

COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
EXPOSE 80/tcp 443/tcp
ENTRYPOINT [ "docker-entrypoint.sh" ]
CMD [ "httpd-foreground" ]

为了dav的数据持久化,使用了数据卷语法
--mount type=bind,source=/src/webapp,target=/opt/webapp
其中,source是主机,target是容器内的目标,默认给的权限是读写。

(与-v参数的区别是--mount不会自动创建主机目录)

随后则是配置Nginx的反向代理,这里和平常的反向代理的配置方法大同小异,主要是注意修改Nginx的最大上传限制,不然大的APP备份很容易的就超过8M。另外如果对家用机的端口安全十分敏感,可以选择-p 127.0.0.1:8080:80强制只监听本地转发的端口,可以起到保护的作用。

关于这个镜像的环境变量,官方给出的说明还是较为详细的,可以去dockerhub上围观。

另外一个小坑是如果使用Digest的认证方式,部分webdav客户端可能出现报错,保险起见还是使用了Basic方式。

Last modification:December 30th, 2019 at 11:53 am
If you think my article is useful to you, please feel free to appreciate

Leave a Comment