为何用 Docker 跑 Mihomo
容器化的价值在于:进程环境可预期、升级回滚简单、与宿主机其它服务隔离。对 Mihomo 而言,官方维护的 metacubex/mihomo 镜像能把「依赖 libc、路径、工作目录」这类差异挡在镜像内部,你只需要关心配置文件与对外暴露哪些端口。这与在桌面装图形客户端是两条路径:Docker 更适合无头服务器、群晖 / QNAP 或希望用 Git 管理 compose 仓库的进阶用户。
默认情况下,容器内监听在 127.0.0.1 的服务不会被宿主机或其它机器访问;要让「宿主机上的浏览器」或「同局域网里的手机」把 HTTP / SOCKS 指到 NAS 上的 Mihomo,必须同时搞定:端口发布(compose 的 ports)、配置里的 allow-lan / bind,以及 NAS 或云厂商的防火墙。下面分步拆开,避免只映射了端口却仍在容器里监听 localhost 的典型坑。
镜像与标签:别盲追 Alpha
Docker Hub 上的 metacubex/mihomo 同时提供 latest、固定版本号(如 v1.19.x)与 Alpha 等标签。生产或「长期挂着不管」的家用场景,建议在 compose 里钉死具体版本号或至少使用 latest 并配合镜像更新策略;Alpha 适合愿意跟上游节奏、能接受偶发回归的测试环境。多架构(amd64、arm64)在主流镜像中已较常见,NAS 上请先确认 CPU 架构再拉取,避免「拉错架构一直重启」。
1目录与卷挂载:持久化什么
Mihomo 在容器内通常以 /root/.config/mihomo 为配置目录(以你所用镜像说明为准)。最省心的做法是:在宿主机建一个目录,例如 ./mihomo,把整个配置目录绑定挂载进去,这样 config.yaml、下载下来的 GeoIP / GeoSite 数据库、规则缓存与运行期生成的文件都在同一棵树里,备份时打包该目录即可。
若你只想单独挂载一个 config.yaml 文件,也可以把单文件挂到容器内对应路径;注意宿主机上该文件须事先存在,否则 Docker 可能创建成目录而非文件。规则集若使用 rule-providers 的本地路径或缓存,同样应落在挂载卷内,否则容器重建后缓存丢失,启动时会重新拉取,既慢也不利于离线环境。订阅格式若需转换,可先参考 Subconverter 订阅转换 再合并进主配置。
2最小 docker-compose:重启策略与卷
下面是一份骨架级 compose:将镜像版本、宿主机目录与端口按你的环境替换。核心字段是 restart: unless-stopped(或 always)与把整个配置目录挂到 /root/.config/mihomo。
services:
mihomo:
image: metacubex/mihomo:v1.19.22
container_name: mihomo
restart: unless-stopped
volumes:
- ./mihomo:/root/.config/mihomo
ports:
- "7890:7890"
- "9090:9090"
7890 常作为 mixed-port(HTTP + SOCKS 复用端口),9090 常作为 external-controller 供 Web 面板或 API 使用;务必与你的 config.yaml 中端口一致,否则映射了错误端口会表现为「宿主机 telnet 通但程序连不上」或反过来。
3端口映射:容器端口 ↔ 宿主机端口
ports 写法 "宿主机:容器"。例如 NAS 局域网 IP 为 192.168.1.50,你在路由器下的设备上将系统或浏览器代理设为 192.168.1.50:7890,流量会到达 NAS 的 7890,再被 Docker 转发到容器内 7890。若希望只本机可用,可写 127.0.0.1:7890:7890,避免把代理端口暴露到局域网(安全上更保守)。
external-controller 若映射到局域网,任何能访问该端口的人都有可能操作内核(视你是否设置 secret、是否启用危险 API 而定)。建议:要么仅绑定 127.0.0.1:9090:9090 再在宿主机用 SSH 隧道管理,要么强密码 / secret 并配合反向代理与访问控制;不要把无鉴权面板直接暴露在公网。
4allow-lan 与监听地址:否则映射了也连不上
仅写 ports 不够:若 Mihomo 在容器内只监听 127.0.0.1,从宿主机网络命名空间进来的转发连接仍可能被拒绝。请在配置中开启 allow-lan: true,并确认 bind-address 一类字段允许在容器内监听 0.0.0.0 或等价「全接口」行为(具体键名以你所用版本文档为准)。改完后重启容器,再在宿主机用 curl -x http://127.0.0.1:7890 或局域网另一台设备访问 NAS IP 做验证。
# Snippet — align ports with compose and your security policy
mixed-port: 7890
allow-lan: true
bind-address: '*'
external-controller: 0.0.0.0:9090
secret: "use-a-long-random-secret"
提示:开放局域网代理意味着同网段设备可走你的出口策略;请在家庭或团队边界内使用,并避免与不可信网络桥接。
bridge 与 host 网络:何时考虑 host
默认 bridge 模式配合 ports 足以覆盖「端口代理 + 面板」场景,网络边界清晰,也便于多容器共存。host 模式让容器直接使用宿主机网络栈,省去一层 NAT,但端口冲突排查更痛苦,且与 compose 多服务编排的隔离性变差。若你计划在容器里开 TUN 接管宿主机全局流量,往往需要 --network host、额外 cap_add(如 NET_ADMIN)以及 /dev/net/tun 设备挂载,复杂度和风险明显高于「只暴露 mixed-port」。这类需求更建议对照 Linux 裸机 TUN 教程 评估是否干脆在宿主机跑内核。
DNS、Geo 与日志:容器里别忽略路径
FakeIP、DoH、Redir-Host 等与宿主机 systemd-resolved 的交互,在容器场景下会少一层「桌面环境」,但DNS 与规则仍须一致,否则会出现「能 ping 通 IP、网页却怪」的现象。详细字段级说明见 Meta 内核 DNS 防泄漏指南。Geo 文件若配置为容器内路径,请确保落在可写且已挂载的卷上,避免每次启动重新下载。
NAS 与云主机:防火墙与安全组
群晖、威联通等系统常有独立防火墙或「仅允许本地网络」策略;VPS 则有云厂商安全组。现象往往是:容器内监听正常、本机 curl 成功,但局域网其它设备连不上——这时应在宿主机上检查 iptables / 防火墙 GUI,确认 7890、9090(若需)已放行。公网 VPS 上不建议把未加防护的 mixed-port 暴露给全网,除非你很清楚自己在做什么。
常见问题:按顺序排
容器反复重启: 先看 docker logs mihomo,多数是 YAML 语法、策略组引用错误或订阅拉取失败。
宿主机能连、局域网不能: 查 allow-lan、bind、宿主机防火墙与 NAS「客户端隔离」类 Wi‑Fi 设置。
端口映射了但连接被拒绝: 核对 config 内端口与 compose ports 是否一致,以及是否只监听了 127.0.0.1。
更习惯图形界面: 服务器 Docker 与桌面客户端可以并存;日常笔记本上想开箱即用,可从 本站下载页 获取 Clash 系客户端,与本文容器部署形成「服务端 + 终端」分工。
合规提醒:请仅在法律与网络使用政策允许的前提下部署代理;企业或校园网络请勿擅自绕行,后果自负。
关于源码:Mihomo 在 GitHub 开源,便于查阅变更与提交 Issue;若需带界面的客户端安装包作对照,请优先使用 本站下载页,与容器镜像分发区分理解。
小结
用 Docker 跑 Mihomo,可复现链路是:选对镜像标签 → 用卷挂载固化配置与数据 → ports 与 config 端口对齐 → allow-lan 与监听地址允许外部接入 → 按场景检查防火墙与是否要用 host/TUN。掌握这套之后,你在 NAS 上改一次 compose 与配置目录,整机迁移时复制同一文件夹即可恢复容器代理行为,比临时手敲 docker run 更易维护。
相比零散脚本,docker-compose 把端口、卷与重启策略写进版本库,长期成本更低;与站内 Linux systemd、DNS、规则集等文章连读,可以把「服务端内核 + 桌面客户端」放在同一套 Clash.Meta 语境里理解。