抽屉里那台屏幕碎了一角的旧手机,电池还有七成,卖二手没人要,扔了又觉得可惜。上周把它翻出来插上充电器,装了 Termux,现在它蹲在路由器旁边跑一个网页和一个下载任务,待机的时候摸上去只是温的。
这篇不吹「旧手机变 NAS」,就把这一路真正卡住人的地方说清楚。
先说它到底跑的是什么
这类工具的原理链条是:Android 系统里装 Termux(一个终端环境),Termux 里装 PRoot-Distro,PRoot-Distro 再去拉 OCI 镜像跑 Linux 程序。termux-containers 就是在这一层上面套了个 YAML 配置和几条命令,让你不用记一堆 proot 参数。
所以它跟真正的 Docker 有两处根本不同,先记住这两条,后面少走很多弯路:
一是没有端口映射,PRoot 和 Termux 共用同一个网络,程序监听哪个端口,手机上就是哪个端口;二是没有内核级隔离,本质上还是同一个 Android 内核里跑进程,只能是「你自己信任的镜像」。
安装就四行:
pkg install git
git clone https://github.com/BHznJNs/termux-containers ~/termux-containers
cd ~/termux-containers
bash install.sh
脚本会 pkg install -y python proot proot-distro,然后在仓库里建一个 .venv 装 PyYAML,最后把 termux-containers 这个命令挂到 $PREFIX/bin,并执行一次 init。
第一个坎:应用商店那个 Termux 别用
如果你手机里那个 Termux 是从 Google Play 装的,先卸掉。商店里那个版本停更很久了,跟现在的 Android 权限模型对不上,pkg 更新经常直接卡住,后面装什么都没法进行。去 F-Droid 或者项目的 GitHub Releases 下 APK,装完再 pkg update。
这一步错了,后面所有报错都指向奇怪的方向,很浪费时间。
顺带说一句,install.sh 里有个检查:如果你不是在 Termux 里跑,它会直接甩一句「安装脚本必须在 Android Termux 中运行。」然后退出。看到这句不用怀疑脚本坏了,是你 ssh 进去了或者用了别的终端。
第二个坎:仓库别放 /sdcard
git clone 的目标必须是 Termux 的私有目录,也就是 $HOME 下面,别图省事 clone 到 /sdcard/Download。
原因不复杂:/sdcard 是 FAT 系的模拟存储,没有 Unix 权限位,也没有软链接,Python 建 venv、pip 装包、PRoot 建 rootfs 这几步都会出问题。而且装完之后这个仓库不能挪,一挪配置里的路径全废,得重新装一遍。
第三个坎:PORT 不是端口映射
看官方示例里那句 PORT: "8080",很容易以为是「把容器 80 映射到手机 8080」。不是。它只是往容器里塞一个叫 PORT 的环境变量,至于程序认不认这个变量,得看镜像本身。nginx 官方镜像不认 PORT,所以示例用的是 nginx-unprivileged,它读这个变量。
因为共用网络,配好之后是在手机浏览器开 http://127.0.0.1:8080,局域网里其它设备就填手机的局域网 IP 加端口,不需要额外做什么转发。反过来说,端口冲突也没人帮你翻译,两个服务都想用 8080,第二个直接起不来。
第四个坎:镜像 tag 一变,容器里的东西就没了
这条是最容易吃亏的。apply 的规则是:环境变量、挂载、启动命令变了,只是重启;但镜像引用或者 tag 变了,它会停掉、删掉这个容器的文件系统、重新装。
也就是说,你 exec 进去改的配置、装的包,全在容器内部,改一次镜像就没了。想留下来,就得在 YAML 里挂出来:
volumes:
- type: directory
source: ./data/web
target: /usr/share/nginx/html
source 写相对路径时,基准是 YAML 文件所在的目录,不是当前 shell 的位置。目录不存在会自动建,但 type: file 的文件必须自己先放好,不然校验直接不过。
第五个坎:手机会替你杀进程
这是所有「旧手机当服务器」方案共同的死穴,不是这个项目的问题。Android 12 之后有个 phantom process 的限制,后台进程一多就整片清掉,加上各家 ROM 自己的省电策略,你第二天早上会发现服务没了。
能做的三件事:Termux 里执行 termux-wake-lock 拿一个唤醒锁;系统设置里把 Termux 的电池优化关掉、允许后台活动;再把 Termux 加进最近任务锁定,别让一键清理带走。做完这些也不敢保证百分百活着,所以别拿它跑不能断的东西。
日常几条命令:termux-containers apply 应用配置,termux-containers status 看运行状态,termux-containers stop web 停单个服务。
它能干什么,干不了什么
它适合干什么:内网里一个静态页、一个 webhook 接收端、一个定时跑的小脚本、一个 aria2。不适合干什么:需要稳定在线的服务、需要跑 x86 镜像的东西、需要真隔离的多租户场景。
我现在的用法就挺没野心的——手机扔在路由器旁边,想起来才 status 看一眼。你们抽屉里那台旧手机,最后都拿去干什么了?