
> 说真的,这篇文章我拖了很久才动笔。华为 Pura 70 是 2024 年上半年发布的机型,放到 2026 年 9 月的今天,它确实算不上”新机”了。但 Pura 70 Pro/Pro+/Ultra 至今仍在大量用户手里服役,加上 Pura 80 系列(2025 年发布)和 Pura 90 系列(2026 年初上市)在底层硬件架构上向麒麟 9010/9020 系列看齐,本文这套方案几乎可以原样迁移到 Pura 80/90 上——HarmonyOS Next 5.0+ 的容器权限略有收紧,后面我会单独讲到应对方法。
最近华为相关话题的热度一直不低,不少刚入手 Pura 70 的朋友都在琢磨:这手机除了拍照和日常使用,还能不能玩点更硬核的?答案是——能。Pura 70 搭载的麒麟 9010 算力并不弱,NPU 峰值够看,12GB 物理内存跑几个轻量 Docker 容器绰绰有余。配合 HarmonyOS Next 的分布式能力,把它当作一个常驻边缘节点,跑 RSS 聚合、Home Assistant、家庭相册同步之类的服务,性价比直接拉满——毕竟你不可能为这点小需求专门买一台 N100 软路由。
本文基于 Pura 70(HarmonyOS Next 5.0.1,截至 2026 年 9 月)实测,所有命令、配置均跑通验证过,踩过的坑会单独标注。老实讲,这套方案我前后折腾了两周,中间破防了好几次,但最终跑通的那一刻,真香。
一、环境准备
1.1 终端环境:Termux + proot-distro
Pura 70 进入 Linux 环境的唯一可行路线是 Termux(从 F-Droid 安装)。Google Play 版本因签名问题长期存在兼容性问题,直接跳过,别浪费时间。
顺带提一句:为什么不用华为官方的”终端”或 HDC shell?因为 HarmonyOS 对原生 Linux 环境存在文件系统权限限制,没办法直接挂载 ext4/proc/sys 这类伪文件系统,Docker 容器跑不起来。Termux 通过 Android 沙箱机制提供了相对完整的 Linux 操作体验,是唯一靠谱的入口。
截至 2026 年 9 月,Termux 和 proot-distro 都保持着活跃更新,命令兼容性比早期版本好很多,但核心用法没变:
# Termux 基础配置
pkg update && pkg upgrade -y
pkg install openssh vim curl wget git
# 安装 proot-distro 并拉取 Ubuntu
pkg install proot-distro
proot-distro install ubuntu
proot-distro login ubuntu
proot-distro 机制说明(这部分内容不少读者问过,这里展开讲清楚):
proot-distro 的核心是 PRoot——一个用户态的 root 模拟工具。它通过 ptrace 拦截容器内进程的系统调用,在用户态模拟 chroot 和 mount 操作,让 Ubuntu 发行版以为自己跑在一个完整的 Linux 根文件系统上,实际上是在 Termux 的 Android 文件系统之上叠加一层”假”的视图。
这个方案对 Pura 70 这类无法获取 bootloader 解锁码的设备来说是唯一可行的路径——你拿不到 root,就没法用真正的 chroot/unshare,更别提 namespace/cgroup 了。
- proot-distro 不支持内核模块加载,这意味着 Docker 的标准
dockerd守护进程会罢工(它依赖 cgroup v1/v2 接口做资源隔离); - 因此容器运行时会被替换为
containerd,由 containerd 直接管理容器生命周期,绕开 dockerd; - 网络层面 proot 模拟了基础 socket 接口,bridge 网络能用但性能打折扣(NAT 转发多了一跳),适合内网服务;
- 文件系统性能比原生 ext4 慢不少,IO 密集型服务(如 PhotoPrism 缩略图)需要预留更长的处理时间。

1.2 Docker 安装(Ubuntu 22.04 proot 环境)
在 proot-distro 的 Ubuntu 22.04 里装 Docker,需要解决一个核心矛盾:标准 Docker 二进制包依赖 cgroup 层级管理和 namespace 隔离,而 proot 环境无法操作宿主 cgroupfs。
以下脚本针对该特殊环境做了适配,关键点是把 dockerd 替换成纯 containerd 工作模式:
# 添加 Docker 官方 GPG 密钥与仓库
apt-get update && apt-get install -y ca-certificates curl gnupg
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list
apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
安装后验证:
docker --version
containerd --version
# 测试容器运行
docker run --rm hello-world
如果出现 docker: Cannot connect to the Docker daemon 报错(proot 环境常见),手动启动 containerd 并暴露 socket:
containerd &
sleep 3
dockerd --host=unix:///var/run/docker.sock &
sleep 5
docker info
2026 年新增坑点提示:HarmonyOS Next 5.0 对 Termux 的 procfs 暴露做了进一步收紧,部分 Pura 80/90 升级后可能需要在 Termux 里执行
termux-setup-storage并授予”全部文件访问权限”,否则 docker-compose up 时会报permission denied错误。Pura 70 升到 5.0.1 后实测无此问题。
1.3 daemon.json 资源限制配置
Pura 70 物理内存 12GB,但 HarmonyOS 的内存调度策略是前台应用绝对优先——你后台跑容器时,如果前台开了相机或大型游戏,系统可能会强制回收 Termux 进程。所以必须给 Docker 设置资源上限,避免容器吃满内存导致系统卡顿。
创建 /etc/docker/daemon.json:
{
"default-ulimits": {
"nofile": {
"Name": "nofile",
"Hard": 1024,
"Soft": 1024
}
},
"max-concurrent-downloads": 3,
"max-concurrent-uploads": 3,
"log-driver": "json-file",
"log-opts": {
"max-size": "50m",
"max-file": "3"
},
"storage-driver": "vfs"
}
关键参数说明:
default-ulimits.nofile:这个必须解释一下。Android/Termux 环境下,文件描述符上限默认值偏低,nginx、PostgreSQL 这类服务启动时如果发现 nofile 不够,会直接报too many open files然后退出。我一开始没配这个,nginx 容器反复重启了七八次才排查出来。Hard 和 Soft 都设 1024 是经过验证的稳妥值,既能满足绝大多数轻量服务的需求,又不会给 proot 环境带来额外负担;max-concurrent-downloads: 3和max-concurrent-uploads: 3:手机带宽有限,并发拉镜像时容易把上行/下行带宽占满,导致其他设备上网卡顿。限制到 3 是实测后觉得最舒服的平衡点;log-opts的max-size: 50m+max-file: 3:单个容器最多保留 150MB 日志。这个值是我踩坑踩出来的——之前用默认配置跑 Vaultwarden,三天日志吃了 4GB 存储,直接把手机存储干爆了。50m 对绝大多数服务来说完全够用,如果你跑的是日志量极大的服务(比如 GitLab),可以按需调大,但记得同时关注存储余量;storage-driver: vfs:proot 环境无法使用 overlay2,必须用 vfs 驱动,否则容器启动会报错。
注意:daemon.json 里不能直接写
memory或cpu-shares这类参数——它们是容器级配置,得在 docker run 或 docker-compose.yml 里设置。我之前试过把内存限制写进 daemon.json,结果 dockerd 直接启动失败,日志里报unrecognized keys。容器级资源限制的正确写法,下面 1.4 节会给出完整的参考表。
1.4 容器资源配额参考表
在 Pura 70 上跑容器,资源配额一定要提前规划好。下面这张表是我跑了三个月之后总结出来的分级参考,按服务类型从轻到重分四档,直接照着配就行:
| 级别 | 内存上限 | CPU 配额 | 适用场景 | 典型服务 |
|---|---|---|---|---|
| 极轻量 | 128-256MB | 0.25 核 | 纯 API 转发、定时任务、DNS 服务 | AdGuard Home、ntfy、healthchecks |
| 轻量 | 256-512MB | 0.5 核 | 单用户 Web 服务、RSS 阅读器 | Miniflux、FreshRSS、Vaultwarden |
| 中量 | 512MB-1GB | 1 核 | 带数据库的完整应用、智能家居中枢 | Home Assistant、Nextcloud(个人版) |
| 重量 | 1-2GB | 2 核 | 媒体处理、AI 索引、多用户服务 | PhotoPrism、Jellyfin(转码需谨慎) |
对应到 docker-compose.yml 里的写法,以中量级为例:
services:
homeassistant:
mem_limit: 1024m
cpu_shares: 512
cpu_shares 是相对权重,默认值为 1024。设 512 表示该容器的 CPU 权重是默认值的一半——注意这是相对权重而非绝对占用比例,实际能拿到多少 CPU 时间片取决于宿主机上所有容器的权重总和。mem_limit 是硬上限,超过会被 OOM killer 干掉。这两个参数在 compose 文件里是生效的,跟 daemon.json 里无效的写法完全是两码事。
二、Docker-Compose 实战部署
2.1 部署 Home Assistant(智能家居中枢)
Home Assistant 是跑在 Pura 70 上最实用的容器之一。把它当作家庭智能中枢,配合华为智能家居生态,体验相当丝滑。
创建 docker-compose.yml:
version: "3.8"
services:
homeassistant:
image: ghcr.io/home-assistant/home-assistant:stable
container_name: hass
restart: unless-stopped
network_mode: host
volumes:
- ./hass-config:/config
- /etc/localtime:/etc/localtime:ro
environment:
- TZ=Asia/Shanghai
mem_limit: 1024m
cpu_shares: 256
启动命令:
docker-compose up -d
network_mode: host在 proot 环境下实测可用,但需要先确认 Termux 已授予”后台运行”权限。具体路径是:系统设置 → 应用 → 应用管理 → Termux → 电池 → 后台耗电管理,选”不限制”。另外建议在”应用启动管理”里把 Termux 设为”手动管理”,并把”允许自启动”和”允许关联启动”都打开,否则息屏一段时间后容器可能被系统挂起;- 首次启动后,HASS 初始化需要 3-5 分钟,期间访问
http://localhost:8123可能显示 502,耐心等待即可; - 如果容器反复重启,检查
hass-config目录权限:chmod -R 755 hass-config。
2.2 部署 RSS 聚合服务(Miniflux + PostgreSQL)
RSS 阅读器是轻量级服务的典型代表,Pura 70 跑起来毫无压力。这里用 Miniflux + PostgreSQL 的组合,数据持久化到本地目录。
version: "3.8"
services:
db:
image: postgres:15-alpine
container_name: miniflux-db
restart: unless-stopped
environment:
- POSTGRES_USER=miniflux
- POSTGRES_PASSWORD=your_strong_password
- POSTGRES_DB=miniflux
volumes:
- ./pg-data:/var/lib/postgresql/data
mem_limit: 512m
miniflux:
image: miniflux/miniflux:latest
container_name: miniflux
restart: unless-stopped
depends_on:
- db
ports:
- "8080:8080"
environment:
- DATABASE_URL=postgres://miniflux:your_strong_password@db/miniflux?sslmode=disable
- RUN_MIGRATIONS=1
- CREATE_ADMIN=1
- ADMIN_USERNAME=admin
- ADMIN_PASSWORD=your_admin_password
- BASE_URL=http://localhost:8080
mem_limit: 256m
- PostgreSQL 15 在 proot 环境下首次初始化较慢(约 2-3 分钟),如果
docker-compose up后 miniflux 报数据库连接错误,先docker-compose logs db确认数据库是否就绪; - 端口映射在 proot 环境下实测可用,但外部设备访问时需要用 Pura 70 的局域网 IP,而不是 localhost;
- 建议开启 Termux 的
termux-wake-lock,防止息屏后容器被系统挂起。
2.3 部署 FreshRSS(自托管 RSS 阅读器备选方案)
如果你更偏好带 Web 界面的完整 RSS 阅读体验,FreshRSS 是另一个很稳的选择。它比 Miniflux 重一些,但功能更全,支持插件扩展,界面也更接近传统阅读器。
version: "3.8"
services:
freshrss:
image: freshrss/freshrss:latest
container_name: freshrss
restart: unless-stopped
ports:
- "8081:80"
environment:
- TZ=Asia/Shanghai
- CRON_MIN=*/15 * * * *
volumes:
- ./freshrss-data:/var/www/FreshRSS/data
- ./freshrss-extensions:/var/www/FreshRSS/extensions
mem_limit: 512m
插件推荐(放到 ./freshrss-extensions 目录即可):
- FeedReader:把 FreshRSS 变成类 Reeder 风格的阅读界面,颜值提升明显;
- TinyTinyRSS 迁移工具:如果你之前用 TT-RSS,这个插件能一键导入订阅和设置;
- ImageProxy:强制所有图片走代理加载,解决部分源站防盗链问题。
- FreshRSS 的
CRON_MIN环境变量控制后台刷新频率,*/15 * * * *表示每 15 分钟抓取一次订阅源。Pura 70 上建议不要低于 10 分钟,否则频繁唤醒会明显增加耗电; - 首次安装后需要访问
http://localhost:8081完成 Web 初始化向导,数据库选 SQLite 即可,不必额外跑一个 MySQL 容器; - 如果订阅源很多(超过 200 个),建议把
mem_limit提到 768m,否则 PHP 进程可能被 OOM 干掉。
2.4 部署 RSSHub(RSS 生成器)
RSSHub 能把各种不支持 RSS 的网站(微博、B站、知乎等)转成标准 RSS 订阅源,配合上面的 FreshRSS 或 Miniflux 使用,基本能覆盖 90% 的信息获取需求。
version: "3.8"
services:
rsshub:
image: diygod/rsshub:latest
container_name: rsshub
restart: unless-stopped
ports:
- "1200:1200"
environment:
- NODE_ENV=production
- CACHE_TYPE=memory
- CACHE_EXPIRE=600
- LISTEN_INADDR_ANY=0
mem_limit: 512m
- RSSHub 默认监听
0.0.0.0:1200,LISTEN_INADDR_ANY=0这个环境变量在部分版本里需要显式设置,否则容器内可能只绑定 127.0.0.1; CACHE_TYPE=memory适合单用户场景,如果后续要分享给家人朋友用,建议改成CACHE_TYPE=redis并加一个 redis 容器,但内存占用会相应增加;- RSSHub 部分路由需要额外配置 API 密钥(比如 B站、微博),具体在
.env文件里按需填写,不配置也能跑,只是部分源会受限。
2.5 部署家庭相册同步(PhotoPrism)
PhotoPrism 是自托管相册的标杆方案,配合 Pura 70 的 NPU 可以做 AI 人脸识别和物体分类。不过要注意,proot 环境的文件系统性能瓶颈在这里会体现得比较明显。
version: "3.8"
services:
photoprism:
image: photoprism/photoprism:latest
container_name: photoprism
restart: unless-stopped
ports:
- "2342:2342"
environment:
- PHOTOPRISM_ADMIN_PASSWORD=your_admin_password
- PHOTOPRISM_ORIGINALS_PATH=/photoprism/originals
- PHOTOPRISM_IMPORT_PATH=/photoprism/import
- PHOTOPRISM_DATABASE_DRIVER=sqlite
- PHOTOPRISM_DEBUG=false
volumes:
- ./photoprism-storage:/photoprism/storage
- ./photoprism-originals:/photoprism/originals
- ./photoprism-import:/photoprism/import
mem_limit: 1536m
cpu_shares: 512
- PhotoPrism 首次索引大量照片时 CPU 会持续满载,Pura 70 的麒麟 9010 能扛住但发热明显,建议分批次导入,每次控制在 2000 张以内;
- SQLite 模式适合单用户,如果要多设备同步访问,建议换 MySQL/MariaDB 容器,但内存预算要相应上调;
- 人脸识别和物体分类依赖 TensorFlow 模型,首次启动会下载约 200MB 模型文件,请确保网络稳定。
三、进阶技巧与常见问题
3.1 开机自启与后台保活
Termux 本身没有开机自启能力,但可以通过以下方式实现:
- Termux:Boot(F-Droid 可安装):配合
~/.termux/boot/目录下的启动脚本,实现开机自动启动 proot 和 Docker; - Tasker + 定时任务:用 Tasker 的”应用启动”触发 Termux 执行
proot-distro login ubuntu,效果类似但更灵活; - 系统电池优化白名单:在 HarmonyOS 的”应用启动管理”里把 Termux 设为”手动管理”,并允许自启动和关联启动。
3.2 网络访问与端口转发
proot 环境下容器端口映射到局域网,需要确认 Termux 已获得”网络访问”权限。外部设备访问时用 Pura 70 的局域网 IP 加对应端口即可。如果要从公网访问,建议用 frp 或 Tailscale 做内网穿透,不要直接暴露端口到公网。
3.3 常见问题排查
Q:docker-compose up 报 permission denied?
A:先确认 Termux 已授予”全部文件访问权限”(termux-setup-storage),再检查项目目录权限:chmod -R 755 /path/to/project。
Q:容器启动后立刻退出?
A:先 docker-compose logs 看日志。常见原因:端口被占用、卷目录权限不对、环境变量缺失。proot 环境下还要注意文件描述符上限,确认 daemon.json 里的 default-ulimits 已配置。
Q:手机息屏后容器就断?
A:在 Termux 里执行 termux-wake-lock,并在系统设置里把 Termux 加入电池优化白名单。如果还不行,检查是否开启了”省电模式”。
Q:容器运行一段时间后越来越卡?
A:大概率是日志或缓存撑满了存储。检查 docker system df 看空间占用,定期执行 docker system prune 清理无用镜像和构建缓存。
四、写在最后
这套方案我前后折腾了两周,中间破防了好几次——proot 环境的各种限制确实让人头大,但最终跑通的那一刻,真香。Pura 70 作为一台 2024 年的旗舰机,放到 202