
背景
小米路由器(基于 OpenWrt 定制)跑 Docker 这件事,本质上就是在路由器 SoC 的有限资源里抠性能。说白了,它和桌面 Linux 不一样:OpenWrt 的网络栈、文件系统、用户权限模型都是「为路由器优化过的」,所以 docker compose 配置稍微带点「标准写法」的惯性,就会踩坑。

本文聚焦实操中最常碰到的三类报错,把每类问题的现象、原因、排查、解决拆成四段式讲清楚,所有命令都基于截至 2026 年 08 月的主流通行版本,可以直接复制粘贴复用。
适用设备:小米 BE6500 Pro、AX9000、万兆路由器等 1GB+ 内存机型;512MB 机型的部分方案会单独标注
问题一:network bridge 冲突导致容器无法启动
现象
docker compose up -d
# Error response from daemon: network bridge is not found
# 或:failed to create network: Error response from daemon: Pool overlaps with other one
可能原因
OpenWrt 的网络架构跟桌面 Linux 不一样:默认网桥由系统(netifd)管理,docker0 和 br-lan 在容器启动前就被预置好了。如果你在 compose.yaml 里手动写 driver: bridge,Docker 守护进程会尝试再创建一个 bridge,结果就和 OpenWrt 现有的网桥撞车。
排查命令
# 查看当前 Docker 网络
docker network ls
# 查看已存在的网桥
ip link show | grep -E 'docker|br-lan|br-'
# 查看 Docker 守护进程配置
cat /etc/docker/daemon.json
解决步骤
1. 先看现状,确认是哪个网桥冲突
ip link show | grep docker
# 通常能看到 docker0 已存在
docker network ls
2. 改用默认网络(最简单的修复)
OpenWrt 下最稳的写法是干脆不写 networks 块,让 Docker 自动用默认网络:
services:
ollama:
image: ollama/ollama:latest
container_name: ollama
restart: unless-stopped
ports:
- "11434:11434"
volumes:
- ./ollama_data:/root/.ollama
environment:
- OLLAMA_HOST=0.0.0.0
注:当前主流的 docker compose v2 已经不再需要
version字段。
3. 如果一定要手动指定网络,记得避开 OpenWrt 的网段
networks:
default:
driver: bridge
ipam:
config:
- subnet: 172.28.0.0/16
进阶:多容器互联(Ollama + OpenWebUI)
如果同时部署 Ollama 和 OpenWebUI,建议建一个专用网络让两个容器互通:
services:
ollama:
image: ollama/ollama:latest
container_name: ollama
restart: unless-stopped
ports:
- "11434:11434" # 对外暴露
volumes:
- ./ollama_data:/root/.ollama
environment:
- OLLAMA_HOST=0.0.0.0
- OLLAMA_ORIGINS=* # 允许跨域访问
networks:
- ollama-net
openwebui:
image: ghcr.io/open-webui/open-webui:main
container_name: openwebui
restart: unless-stopped
ports:
- "8080:8080"
environment:
- OLLAMA_BASE_URL=http://ollama:11434
depends_on:
- ollama
networks:
- ollama-net
networks:
ollama-net:
driver: bridge
ipam:
config:
- subnet: 172.28.0.0/16
常见变体报错对照表
| 报错信息 | 原因 | 解决方案 |
|---|---|---|
network bridge not found |
手动指定了不存在的网络名 | 改用默认网络或先 docker network create |
port is already allocated |
11434 端口被占用 | 换端口如 11435:11434 或 kill 占用进程 |
pool overlaps with other one |
自定义网段和现有网桥冲突 | 换用 172.28.0.0/16 等冷门段 |
driver failed programming external connectivity |
iptables 规则冲突 | 重启 Docker 服务 /etc/init.d/dockerd restart |
问题二:存储卷路径权限拒绝
现象
docker compose up -d
# Error response from daemon: Access denied on path /root/.ollama
# 或容器启动后日志反复报:mkdir /root/.ollama: permission denied
可能原因
OpenWrt 上 Samba、NFS 共享目录归属 nobody:nogroup,而 Docker 容器内默认以 ollama(uid 1000)进程跑,挂载卷写入时宿主权限校验失败。说白了就是「容器用户 uid」和「宿主 nobody」对不上。
原理说明
小米路由器 OpenWrt 的 /mnt/storage 这类挂载点,通常被 Samba 服务以 nobody 身份共享,目录属主是 nobody:nogroup。容器里跑的是 Ollama 进程(默认 uid 1000),它看到的挂载目录权限位是不允许 1000 写入的,于是就 permission denied。
排查命令
# 查看目录归属
ls -la /mnt/storage/
# 查看容器内默认用户
docker exec ollama id
# 查看当前用户映射
cat /etc/subuid
cat /etc/subgid
解决步骤
1. 手动建目录并放开权限(粗暴但有效)
mkdir -p /mnt/storage/ollama_data
chmod -R 777 /mnt/storage/ollama_data
2. compose 里显式指定 root(关键的一行)
services:
ollama:
image: ollama/ollama:latest
container_name: ollama
restart: unless-stopped
ports:
- "11434:11434"
volumes:
- /mnt/storage/ollama_data:/root/.ollama
environment:
- OLLAMA_HOST=0.0.0.0
user: "0:0" # 强制 root 权限解决写入问题
3. 用 tmpfs 临时测一下是不是真权限问题
volumes:
- type: tmpfs
target: /root/.ollama
进阶方案:用命名卷绕开文件系统权限怪相
ext4/overlay 的挂载权限怪相(小米路由器刷机分区有它的特殊性),用 Docker 命名卷能比较优雅地绕过:
services:
ollama:
image: ollama/ollama:latest
container_name: ollama
volumes:
- ollama_data:/root/.ollama
volumes:
ollama_data:
driver: local
driver_opts:
type: none
o: bind
device: /mnt/storage/ollama_data
权限问题自查清单
- 宿主机目录已创建
- 目录权限为 777 或 755
- compose 文件中显式指定
user: "0:0" - 尝试
/etc/init.d/dockerd restart - 排查日志:
docker logs ollama
问题三:内存不足导致 OOM Kill
现象
docker compose up -d
# dmesg 中看到类似:
# oom-kill: ... ollama invoked oom-killer, gfp_mask=0x100cca
# 容器状态显示 Exited (137)
老实讲,第一次部署的时候我直接 ollama pull llama3.1:8b,结果没几秒就被 OOM 干了,瞬间破防。后来老老实实换 1B–3B 段位的模型,体感完全两个世界。
可能原因
小米路由器内存通常 512MB–2GB 之间,跑 7B 量化模型(Q4_K_M)勉强够,加载更大模型不加 swap 就直接被内核 OOM Killer 干掉。
原理说明
Linux OOM Killer(Out-of-Memory Killer)是内核兜底机制:物理内存 + swap 全部耗尽时,内核根据 oom_score 杀掉得分最高的进程。Docker 容器虽然有 mem_limit,但若没设置或 swap 缺失,宿主本身被 OOM 时容器也会跟着死。OpenWrt 系统服务(dnsmasq、uhttpd、firewall 等)常驻吃 200–300MB,剩给 Docker 的空间本来就紧。
排查命令
# 查看内存总量与可用
free -m
# 查看 swap 状态
swapon -s
# 看 dmesg 的 OOM 记录
dmesg | grep -i oom
# 容器维度的内存占用
docker stats --no-stream
# 实时内存监控
watch -n 1 'free -m'
# 看容器是否被 OOM 标记
docker inspect ollama | grep -i oom
解决步骤
1. 先看家里内存和 swap 现状
free -m
swapon -s
2. 加 swap 文件(路由器一般默认没有)
dd if=/dev/zero of=/mnt/storage/swapfile bs=1M count=2048
chmod 600 /mnt/storage/swapfile
mkswap /mnt/storage/swapfile
swapon /mnt/storage/swapfile
3. 给容器加硬性内存限制(保守值)
services:
ollama:
image: ollama/ollama:latest
container_name: ollama
restart: unless-stopped
ports:
- "11434:11434"
volumes:
- /mnt/storage/ollama_data:/root/.ollama
environment:
- OLLAMA_HOST=0.0.0.0
- OLLAMA_NUM_PARALLEL=2
- OLLAMA_MAX_LOADED_MODELS=1
mem_limit: 750m
mem_reservation: 512m
user: "0:0"
4. 拉小模型,别硬上 7B
docker exec -it ollama ollama pull phi3:mini # 约 2.3GB
docker exec -it ollama ollama pull llama3.2:1b # 约 1.3GB
docker exec -it ollama ollama pull deepseek-r1:1.5b # 适合 1GB 内存机型
docker exec -it ollama ollama pull qwen3:1.7b # 中文场景表现稳
| 路由器型号 | 内存 | 推荐模型(截至 2026 年 08 月) | 最大并发 |
|---|---|---|---|
| 小米 AX3600 | 512MB | phi3:mini, llama3.2:1b | 1 |
| 小米 AX9000 | 1GB | qwen3:1.7b, llama3.2:3b, deepseek-r1:1.5b | 1–2 |
| 小米 BE6500 Pro | 1GB | qwen3:1.7b, mistral:7b (Q4) | 2 |
| 小米万兆路由器 | 2GB | llama3.2:3b, deepseek-r1:7b, qwen3:4b | 3 |
BE6500 Pro 实测数据(截至 2026 年 08 月):空载系统约 280MB,加 swap 后跑
qwen3:1.7b推理峰值约 620MB,单请求响应延迟 1–3 秒(视 prompt 长度),本地对话场景完全够用。
2026 年适配路由器部署的小模型横评
最近这一年边缘侧部署热度是真高,下面这几个 1B–3B 段位的模型,是我自己在 BE6500 Pro 上跑过、且截至 2026 年 08 月社区评价也比较稳的(长尾关键词:OpenWrt 部署 DeepSeek、小米路由器本地大模型、边缘 AI 部署):
| 模型 | 体积(Q4 量化) | 中文能力 | 英文能力 | 内存占用参考 | 推荐场景 |
|---|---|---|---|---|---|
| deepseek-r1:1.5b | ~1.0 GB | ★★★★ | ★★★ | ~400MB | 推理任务、轻量 Agent |
| qwen3:1.7b | ~1.2 GB | ★★★★★ | ★★★★ | ~500MB | 中文对话首选 |
| llama3.2:1b | ~0.8 GB | ★★ | ★★★★ | ~350MB | 英文场景、轻量补全 |
| llama3.2:3b | ~2.0 GB | ★★★ | ★★★★★ | ~750MB | 1GB+ 内存机首选 |
| phi3:mini | ~2.3 GB | ★★★ | ★★★★ | ~850MB | 综合问答 |
| gemma3:1b | ~0.8 GB | ★★★ | ★★★★ | ~350MB | 低内存兜底 |
注:内存占用为推理 + 模型加载后的峰值参考,实际视 prompt 长度、并发数有 ±100MB 浮动。
个人推荐优先级(BE6500 Pro / 1GB 内存场景):
- 中文对话 →
qwen3:1.7b - 推理 / 数学 →
deepseek-r1:1.5b - 英文任务为主 →
llama3.2:3b
模型拉取、更新、备份流程
拉取模型
# 进入容器拉取
docker exec -it ollama ollama pull <model_name>
# 列出已下载
docker exec -it ollama ollama list
更新模型
# 镜像更新
docker compose pull ollama
docker compose up -d
# 模型单独更新(Ollama 0.5+ 支持)
docker exec -it ollama ollama pull <model_name>
备份已下载的模型
模型文件本身存放在 /mnt/storage/ollama_data/models/ 下(按前文配置),建议定期打包:
# 整机备份
tar -czf ollama_models_$(date +%Y%m%d).tar.gz /mnt/storage/ollama_data/models
# 迁移到另一台设备
scp ollama_models_*.tar.gz root@<新设备IP>:/mnt/storage/
删除不再用的模型
docker exec -it ollama ollama rm <model_name>
关键环境变量调优建议
Ollama 容器有几个环境变量对路由器这种「内存敏感」场景特别重要:
| 变量 | 作用 | 推荐值 |
|---|---|---|
OLLAMA_NUM_PARALLEL |
最大并发推理数 | 1–2(视内存) |
OLLAMA_MAX_LOADED_MODELS |
同时缓存的模型数 | 1(路由器只能这样) |
OLLAMA_KEEP_ALIVE |
模型加载后保留时长 | "5m"(默认 5 分钟) |
OLLAMA_HOST |
监听地址 | 0.0.0.0(局域网可访问) |
OLLAMA_ORIGINS |
跨域白名单 | *(OpenWebUI 用) |
OLLAMA_DEBUG |
调试日志 | 1(排查时临时开) |
完整示例:
environment:
- OLLAMA_HOST=0.0.0.0
- OLLAMA_ORIGINS=*
- OLLAMA_NUM_PARALLEL=1
- OLLAMA_MAX_LOADED_MODELS=1
- OLLAMA_KEEP_ALIVE=5m
完整可用的 docker compose 配置(基于 BE6500 Pro 实测)
services:
ollama:
image: ollama/ollama:latest
container_name: ollama
restart: unless-stopped
ports:
- "11434:11434"
volumes:
- /mnt/storage/ollama_data:/root/.ollama
environment:
- OLLAMA_HOST=0.0.0.0
- OLLAMA_ORIGINS=*
- OLLAMA_NUM_PARALLEL=1
- OLLAMA_MAX_LOADED_MODELS=1
- OLLAMA_KEEP_ALIVE=5m
mem_limit: 768m
mem_reservation: 512m
user: "0:0"
openwebui:
image: ghcr.io/open-webui/open-webui:main
container_name: openwebui
restart: unless-stopped
ports:
- "8080:8080"
environment:
- OLLAMA_BASE_URL=http://ollama:11434
depends_on:
- ollama
networks:
- ollama-net
networks:
ollama-net:
driver: bridge
ipam:
config:
- subnet: 172.28.0.0/16
说明:当前主流的 docker compose v2 已不再需要
version字段,上面配置可直接使用。
总结
说白了,小米路由器跑 Ollama 这事,本质就是三个坑:网络别瞎配、权限别僵持、内存量力而行。把这三个点踩准了,1GB 内存跑个小模型对话是完全没问题的。
如果你打算更进一步(比如加 NPU offload、跑 Agent 框架),建议先去小米万兆路由器那种 2GB+ 的机型上玩,BE6500 Pro / AX9000 这种 1GB 机还是老老实实跑 1B–3B 模型,省心也省电。
常见问题 FAQ
Q1:小米 BE6500 Pro 能不能跑 7B 模型?
A:能跑,但得加 2GB 以上的 swap,并且 mem_limit 调到 1.5g 以上。响应速度会比较慢,单请求推理可能 10 秒以上。日常对话还是 1B–3B 段位更舒服。
Q2:swap 文件放 /mnt/storage 还是 /tmp?
A:建议放 /mnt/storage,因为路由器内部 flash 寿命有限,长期 swap 写入会刷坏存储分区。/mnt/storage 通常是外接 USB 存储,扛得住。
Q3:Ollama 和 OpenWebUI 必须一起装吗?
A:不一定。Ollama 单独启动后,通过 11434 端口提供 API,可以被任何兼容客户端使用(甚至 SSH 里 curl 调用也行)。OpenWebUI 只是其中一个比较舒服的 Web 前端。
Q4:怎么备份已下载的模型?
A:模型文件存放在 /mnt/storage/ollama_data/models/(按本文配置),直接 tar 打包就行,跨设备迁移 scp 即可。
Q5:BE6500 Pro 跑 Ollama 实际功耗多少?
A:在 BE6500 Pro 上加挂两个容器(Ollama + OpenWebUI),空载 + 待机时总功耗约 +1.5W,跑推理峰值约 +3W,整体路由器功耗仍在 12W 以内。
Q6:能跑 DeepSeek-R1 蒸馏版吗?
A:可以。deepseek-r1:1.5b 体积约 1GB,是 1GB 内存路由器上推理 / 数学场景的优选;deepseek-r1:7b 推荐放到万兆路由器(2GB+)上。
Q7:怎么确认容器没被 OOM Kill?
A:dmesg | grep -i oom 看有没有 Killed process 记录;docker inspect ollama | grep OOMKilled 字段为 true 即被杀。
Q8:log 提示 iptables 报错怎么办?
A:OpenWrt 默认 nftables 后端,docker 可能用了旧 iptables,编辑 /etc/docker/daemon.json 加入:
{
"iptables": false
}
然后 /etc/init.d/dockerd restart 即可。
Q9:升级 OpenWrt 后容器全挂怎么办?