玩ARM盒子的人,迟早会走到“自建私有网盘”这一步。手头一台吃灰的ARM设备,刷上Armbian 5.77(Debian 9),跑在老旧内核上,想要一个能传大文件、能在线看文档、能挂到电脑上当网络硬盘的Web网盘,可道云(KodExplorer)是为数不多性能友好、上手又快的选择。这篇文章把我踩过的坑、验证过的方案、以及从镜像选型到最后参数修正的完整过程写出来,照着一路执行即可。
这套部署方案的核心是:在Armbian 5.77上安装并运行Docker,然后通过Docker容器运行可道云及其数据库。系统是32位ARM架构、内核版本旧、软件源大部分失效、Docker官方安装脚本还不一定兼容,这三座大山互相叠加,如果直接沿用网上常见的x86部署教程,大概率会栽在第一步。本文会专门处理这几类问题。可以把它看作一份“老旧ARM设备上运行网盘服务”的实战笔记,目标是让盒子或开发板真正变成一台内网可用的文件服务器,适合有基础Linux命令经验、手上正好有闲置ARM设备的用户参考。
1. 方案设计:为什么自建可道云要走Docker这条路
1.1 镜像选型:一体化镜像还是“官方应用+独立数据库”
在Docker Hub上搜索可道云,能看到的镜像大致分两类。一类是把Nginx、PHP、MySQL全部打包在一体的“全家桶镜像”,启动一个容器就全部跑起来,对小白极度友好,配置量最小。另一类是官方可道云应用镜像加独立数据库容器,应用和数据库分离,更接近生产环境的架构。
我更推荐第二种。原因很朴素:ARM设备性能有限,一旦某个组件出问题,一体化容器重启就把网页和数据库全带崩了,排查起来还得进容器里一层层翻,非常痛苦。而拆开之后,MySQL容器挂了最多是网页报“无法连接数据库”,应用容器还在跑,文件目录还在,心理上踏实得多。更重要的是,分离部署对后续的升级、备份、迁移都更友好——备份数据库单独一个步骤,备份文件目录单独一个步骤,不用把一个几十G的容器整体当文物供着。
我这套方案选的组合是:官方可道云镜像负责跑Web服务,外部单独跑一个数据库容器,版本方面根据ARM架构和Debian 9系统的实际内核情况做适配。数据库用轻量一点的方案,PHP环境由可道云镜像自带的依赖解决,不用自己动手编译一遍扩展,这能省掉大量时间。
1.2 架构兼容性:老ARM设备最容易被忽略的问题
Armbian 5.77这个版本对应的Debian 9,绝大多数载体都是ARMv7 32位架构的盒子或开发板。这个细节直接决定了镜像拉取时的成败。
现代大多数新的Docker镜像只提供了amd64和arm64两种架构,对32位ARM(armhf)的支持从2020年左右开始陆续停止。如果你手头这块板子是armhf架构,直接docker run一个最新官方镜像,会看到“no matching manifest for linux/arm/v7”这类错误。解决办法不是硬刚,而是寻找还在维护的旧镜像标签,或者选择本身带armhf构建的多架构镜像。可道云生态因为用户群体特殊,对旧设备的支持一直做得不错,所以在镜像选择上反而有优势。
先用一条命令确认架构:
uname -m输出是 armv7l 或 armhf,说明你得按32位ARM的套路走;如果输出 aarch64,那是64位架构,反而可以试试新镜像。顺便用docker info看一下系统信息,确认Docker能正常识别当前架构。
1.3 明确目标:这套方案到底能实现什么效果
动手之前先明确预期,免得搭建完才发现不是自己想要的。此方案的最终形态如下:在内网任意一台电脑或手机浏览器里访问盒子IP加端口,打开可道云登录页,可以像使用一个在线文件管理器那样上传、下载、在线预览文档和图片,还可以把它挂载成Windows的网络驱动器,当普通硬盘一样复制粘贴大文件。
性能预期要现实一点。ARM盒子跑PHP网盘,浏览目录、打开文档、在线播放视频都是流畅的,但频繁生成缩略图或同时处理大量文件时CPU会吃紧。外网访问、HTTPS证书这些高级玩法不在本文范围,但方案本身留有余地,后面加反向代理或独立域名都方便。
2. 环境准备:让Debian 9上的Docker跑起来
2.1 先把旧软件源换掉,否则apt会卡到怀疑人生
Armbian 5.77内置的软件源指向的是Debian 9的官方源。Debian 9早已停止维护,官方源里很多路径已不可用。不换源直接apt update,轻则更新列表时报404,重则整个过程卡住不动,像死机一样。换源是这个系统上一切操作的前提。
先备份原文件,然后编辑。对于Debian 9,常见可用源包括某国内镜像站保留的stretch目录。将 /etc/apt/sources.list 换成类似这样的一套:
mv /etc/apt/sources.list /etc/apt/sources.list.bak echo "deb https://mirrors.example.com/debian stretch main contrib non-free" > /etc/apt/sources.list echo "deb https://mirrors.example.com/debian-security stretch/updates main contrib non-free" >> /etc/apt/sources.list apt update注意,上面的mirrors.example.com只是一个占位符,实际使用时要替换成你所处地区能够稳定访问的镜像源地址。不同地区可用性有差异,验证标准只有一个:apt update没有大面积404。如果某个源不行,就换另一个,这也是排查老系统问题时最常见的动作。
2.2 安装Docker的两种路径与选择建议
Debian 9上装Docker,网上攻略基本都是复制Docker官方一键脚本:
curl -fsSL https://get.docker.com -o get-docker.sh这个脚本在老系统上经常翻车。原因在于它需要一个较新的软件依赖环境和可用的Docker APT源,老系统往往不满足条件。我实测下来,最稳的路线反而是直接用Debian自带软件包:
apt install -y docker.io systemctl enable docker systemctl start dockerDebian 9源里自带的docker.io版本虽然不是最新,但对跑可道云这种老PHP应用来说完全够用。容器编排的功能也都有,只是版本号旧一点而已。如果Docker.io版本过低导致Compose功能缺失,再考虑装Docker CE,这属于少数情况。
安装完成后,验证Docker确实能正常工作:
docker version docker info重点看两件事:一是Server端是否正常输出信息,二是Storage Driver是什么。老旧内核上常见的是vfs驱动,性能差一些;若显示overlay2,说明内核情况较好,磁盘效率会高很多。vfs在拷贝大文件时的额外开销差不多在百分之十几到三十之间,对普通内网网盘使用感知不明显,不用过分纠结。
2.3 给Docker单独留一个数据目录,防止把系统盘撑爆
默认情况下Docker所有数据都放在 /var/lib/docker。ARM盒子的存储空间通常很紧张,系统本身占了一部分,SD卡或emmc剩余空间没多少。可道云的文件数据、数据库文件、容器日志都会持续增长,若不分目录,总有一天系统盘被占满,盒子卡成幻灯片。
建议把Docker数据目录放到外接硬盘或大容量分区上。方法是在 /etc/docker/daemon.json 中指定data-root:
{ "data-root": "/mnt/data/docker" }改完重启Docker:
systemctl restart docker此时 /mnt/data/docker 会成为Docker的新家。盒子重启、容器重建、镜像拉取都不会再把系统盘塞满。这一步看似和网盘本身无关,但却是长期稳定运行的关键,建议在正式部署前就做好。
3. 部署实操:数据库与可道云容器的完整搭建过程
3.1 目录规划
可道云的核心数据其实是两部分:文件本身(files目录)和程序配置与系统数据(data目录)。程序代码在容器里,可以随时重建,但文件和数据库是命根子,必须挂载到宿主机目录。
我习惯在宿主机上建立一个清晰的目录结构,后面备份、迁移都直接针对这个目录操作:
mkdir -p /opt/kod/files mkdir -p /opt/kod/db mkdir -p /opt/kod/backup3.2 启动数据库容器
可道云在轻量场景下可以用SQLite,但在多人使用、文件量大、需要稳定事务时,还是要一个独立数据库。我这里用数据库容器,选择的是兼容性极好、在ARM上运行流畅的MariaDB镜像。需要留意的是,新一代的MySQL镜像已经不再提供armhf架构版本,而老版本的镜像往往有对应架构的标签可拉取,这也是很多老设备用户最终的可行路径。
创建自定义网络,让两个容器可以通过服务名互联,而不必依赖宿主机端口回环:
docker network create kodnet然后启动数据库容器:
docker run -d \ --name kod-db \ --network kodnet \ --restart unless-stopped \ -e TZ=Asia/Shanghai \ -e MYSQL_ROOT_PASSWORD=your-strong-password \ -e MYSQL_DATABASE=kodbox \ -e MYSQL_USER=kod \ -e MYSQL_PASSWORD=kod-password \ -v /opt/kod/db:/var/lib/mysql \ -v /etc/localtime:/etc/localtime:ro \ your-registry/mariadb:10.3-bionic以上命令中的镜像地址需要根据你所在环境和实际可拉取的镜像进行调整,尤其要注意架构匹配。密码部分不要照抄,换成自己设置的强密码。TZ环境变量决定容器内时区,不设置会导致文件时间显示差8小时,这是个很容易被忽略又很糟心的细节。MYSQL_DATABASE、MYSQL_USER、MYSQL_PASSWORD这三个环境变量是初始化用的,首次启动数据库容器时自动创建对应库和用户。
3.3 启动可道云应用容器
可道云官方提供了一个打包好的Docker镜像,这个镜像把Nginx、PHP-FPM、可道云程序本体都包含在内,开箱即用。启动时挂载文件目录,把端口映射出来:
docker run -d \ --name kodbox \ --network kodnet \ --restart unless-stopped \ -p 8080:80 \ -e TZ=Asia/Shanghai \ -v /opt/kod/files:/var/www/html/data/files \ -v /opt/kod/data:/var/www/html/data \ your-registry/kodbox:latest端口选用8080而不是80,避开常见服务冲突。如果你打算在宿主机上再套一层Nginx反代,这里甚至可以不用映射端口,只在kodnet内部用服务名访问,这里不做展开。
需要留意的是首次启动时,容器内部的很多数据文件是基于初始状态生成的。先启动容器,让它初始化程序本体,再停掉容器,修改一部分配置文件,然后再次启动。直接一开始就挂载一个宿主机空目录,有可能导致启动时找不到必要的文件。更稳妥的做法是:先不带数据卷启动一次,确认程序正常,再停掉,把容器内关键目录拷出来,最后带数据卷重新启动。这个“先进去跑一遍再挂载”的流程,是处理“容器初始化时生成文件”类应用时非常通用的经验。
3.4 用Docker Compose把整个服务编排起来
上面的命令单独敲没问题,但如果要把这套方案长期跑下去,我建议还是用Compose做成一个可复现的编排文件。写一个 docker-compose.yml,内容大致如下:
version: "2" services: db: image: your-registry/mariadb:10.3-bionic container_name: kod-db restart: unless-stopped environment: - TZ=Asia/Shanghai - MYSQL_ROOT_PASSWORD=your-strong-password - MYSQL_DATABASE=kodbox - MYSQL_USER=kod - MYSQL_PASSWORD=kod-password volumes: - /opt/kod/db:/var/lib/mysql - /etc/localtime:/etc/localtime:ro networks: - kodnet app: image: your-registry/kodbox:latest container_name: kodbox restart: unless-stopped depends_on: - db ports: - "8080:80" environment: - TZ=Asia/Shanghai volumes: - /opt/kod/files:/var/www/html/data/files - /opt/kod/data:/var/www/html/data networks: - kodnet networks: kodnet: driver: bridgeCompose版本特意用version: "2",因为老版本Docker对新版Compose文件格式的兼容性不佳。如果docker-compose命令不可用,用docker-compose up -d启动即可,没有意外的话,两个容器会先后拉起来。
首次访问浏览器,输入http://盒子IP:8080,看到可道云的安装引导页。安装时数据库主机名填 db,而不是 127.0.0.1——两个容器在同一自定义网络中,必须用服务名访问数据库。数据库名、用户名、密码填上面初始化时设置的那组。管理员账号和密码自行设置,设置好后正式进入可道云界面。
3.5 安装后的权限修正
可道云安装完成后,偶尔会遇到“目录不可写”或“文件上传后无法读取”的提示。这是因为容器内的Web服务以www-data用户运行,而挂载到宿主机的目录文件属主可能不对。进入容器修正权限是常见操作:
docker exec -it kodbox chown -R www-data:www-data /var/www/html/data这种权限修正操作在每次重建容器之后最好都执行一遍,否则会出现文件列表能看到但打不开的诡异问题。
4. 安装后的关键配置与性能调优
4.1 突破上传大小限制:PHP和Nginx两个关口都要改
可道云默认的PHP上传上限通常是2M或8M,对于网盘这个核心用途来说是远远不够的。必须修改PHP配置和Nginx配置两个方面的限制,任何一个不调,上传大文件时都会报错。
第一种修改方式是在容器里直接改文件。可道云容器内部的PHP配置文件路径一般在 /etc/php/ 下的php.ini,Nginx的站点配置文件一般在 /etc/nginx/conf.d/。找到并修改:
upload_max_filesize = 2048M post_max_size = 2048M max_execution_time = 3600 max_input_time = 3600 memory_limit = 512MNginx侧对应的是在server块里加一行:
client_max_body_size 2048m;在容器里改完之后重启容器docker restart kodbox,配置就会生效。但这有一个隐患:容器一旦重建,所有修改全部消失,又得重来一遍。真正持久化的做法是在宿主机上准备自定义配置文件,再通过卷挂载的方式覆盖进容器。例如宿主机 /opt/kod/conf/php-uploads.ini 写到容器 /etc/php/conf.d/99-uploads.ini,宿主机 /opt/kod/conf/nginx-server.conf 挂到容器 /etc/nginx/conf.d/server-custom.conf。这样重建容器后自定义参数依然生效,整个部署才称得上“可复现”。
4.2 伪静态配置:可道云的URL美化
可道云支持通过URL重写去掉路径中的index.php,让链接更简短,利于分享和收藏。如果不做伪静态配置,访问时链接会变成类似http://ip:8080/index.php?path=/foo,功能不受影响,但复制分享链接时又长又乱。
容器内置的Nginx配置通常已经处理好了可道云的伪静态规则,无需额外改动。如果要自行配置,可道云官方文档提供了一套针对Nginx的规则,核心是把非真实存在的路径请求转发到index.php。检查方式很简单:在可道云设置里开启“伪静态”,如果一个文件分享出来能正常访问,说明规则生效;如果出现404,就把「伪静态增强」关掉,恢复默认参数链接方案即可。这个功能不影响核心使用,属于锦上添花,不用在此处耗费太多时间。
4.3 缩略图与定时任务:线上看图的最后一环
可道云在浏览图片目录时会生成缩略图。如果部署完成后发现图片列表加载很慢,或者干脆不显示预览,多半是缩略图服务没有正常工作。原因通常有三个:PHP缺少GD扩展或ImageMagick扩展;缩略图生成队列没有消费;data目录不可写。
确认扩展是否加载可以在可道云后台的“环境检测”中直接查看,缺少GD扩展时去容器内安装并启用扩展。这属于依赖程序包的补全操作。定时任务则确认容器内是否运行了cron服务,以及是否配置了可道云的定时任务。实际操作中,ARM设备上图片一次导入成百上千张时,缩略图生成会很慢,建议分批导入,同时把PHP的max_execution_time调大一些,避免中途被掐断。
4.4 老旧ARM设备的内存管理
ARM盒子通常只有1G到2G内存。如果同时跑数据库容器和可道云容器,内存分分钟见底。一个靠谱的思路是给每个容器设置内存上限,防止某个容器吃光内存后整个系统OOM。
在Compose文件中加入:
mem_limit: 512M这样容器只能使用512M内存。配合swap分区或zram,整体体验会稳定不少。另外数据库容器里可以调小innodb_buffer_pool_size,默认值对小块内存的设备太奢侈。在数据库容器启动参数中加上:
command: --innodb-buffer-pool-size=128M可道云这边PHP的memory_limit也不要设太高,512M已经够用。实测下来,用这种配置跑一个三五个人的小团队内网共享,文件浏览、搜索、在线预览都相当流畅,不会卡到无法使用。并发上传大文件时CPU会一直是满载状态,这是ARM设备的硬件瓶颈,靠软件调优只能缓解,没法根治。
5. 高频故障排查与数据备份建议
5.1 故障速查表
部署过程中真正花时间的往往不是安装本身,而是排错。下面按故障现象、常见原因、解决办法三条线整理一张速查表,都是实际操作中比较常见的场景。
| 症状 | 常见原因 | 解决办法 |
|---|---|---|
| 安装页提示无法连接数据库 | 数据库容器未就绪,或主机名写错 | 等待数据库容器初始化完成,确保主机名填db而非127.0.0.1 |
| 上传大文件提示413 Request Entity Too Large | Nginx的client_max_body_size未调整 | 在Nginx配置中增大该参数并重启容器 |
| 上传成功但在线列表看不到文件 | PHP的post_max_size小于实际文件大小 | 确认post_max_size、upload_max_filesize两项都大于目标文件大小 |
| 图片列表不显示缩略图 | 缺少GD/Imagick扩展,或定时任务未运行 | 安装对应扩展,确保容器内cron运行,检查后台任务状态 |
| 容器重启后无法访问网页 | 端口映射改变或容器内php-fpm启动异常 | 检查端口映射,查看容器日志定位php-fpm异常 |
| 文件上传后打开是空白页 | data目录权限错误 | 重新chown www-data:www-data到data目录 |
| 整机内存被占满,OOM杀进程 | 容器内存未限制,MySQL缓冲池过大 | 设置mem_limit,调小innodb_buffer_pool_size |
5.2 定期备份:文件数据和数据库都要留一手
网盘上存的东西都是自己的心血,备份优先级应该高于一切。数据库备份用mysqldump定期导出即可,在宿主机上写一个简单的cron脚本:
#!/bin/bash mysqldump -h127.0.0.1 -uroot -pyour-strong-password kodbox > /opt/kod/backup/kod-$(date +%F).sql tar czf /opt/kod/backup/files-$(date +%F).tar.gz -C /opt/kod/files . find /opt/kod/backup -mtime +7 -exec rm {} \;注意mysqldump要连到容器的对外端口,或直接在Compose网络中用容器名连接。数据库容器未映射3306端口到宿主机时,可以进入容器或在应用容器内执行命令,按照自己的实际网络方案调整连接地址。备份脚本存为 /opt/kod/backup.sh,然后加入crontab:
crontab -e 0 3 * * * bash /opt/kod/backup.sh每天凌晨3点自动备份,保留7天数据。这个脚本本身也值得定期验证,因为备份文件有没有正确生成,只有恢复过才知道。
5.3 容器日志别让磁盘雪上加霜
容器默认会把日志写到 /var/lib/docker/containers 下,长期运行可能产生几个G的日志文件。对存储紧张的ARM设备来说,这很伤。建议在Docker daemon配置中限制日志大小:
{ "data-root": "/mnt/data/docker", "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" } }重启Docker后,新容器就会只保留最近3个10M的日志文件。这个配置对各类容器都适用,属于一劳永逸的基础调优。
5.4 容器重建与迁移的完整流程
一旦需要更换宿主机或迁移数据,这套部署方案的迁移流程非常顺畅:备份数据库和文件目录,在新设备上重新构建Compose服务,恢复备份数据,修正权限,即可无缝衔接。具体操作是,先在旧设备执行一次手动备份,然后在新设备完成基础环境搭建和Compose启动,停止应用容器后将备份的数据文件恢复到对应挂载目录,再启动应用容器。如果没有科学地规划挂载目录,迁移时就得从容器底层文件系统里慢慢捞数据,非常痛苦。
写在最后的一个经验
这套方案在我手里跑了大半年,最深的体会是:老旧ARM设备只要不折腾、不频繁换镜像版本,完全可以胜任“家庭内网文件共享”这个角色。稳定性来源不是某个具体的镜像版本,而是合理的数据挂载规划、克制的资源限制、以及一套能自动执行的备份机制。操作过程中我最推荐的策略是把所有自定义配置全部落到宿主机上的挂载文件里,容器本身当成可随时扔掉重建的组件。这样不管容器怎么折腾,数据还在,配置还在,几分钟就能把服务拉起来。定期检查一下备份是否正确生成,比什么都重要。