avatar

范伟彬个人网

https://fanweibin.cn

  • 首页
  • 归档
  • 链接
  • 关于
  • AI 导航
  • 健康指南
主页 Ubuntu Server 24.04 使用 Docker Compose 部署 Mihomo 完整指南
文章

Ubuntu Server 24.04 使用 Docker Compose 部署 Mihomo 完整指南

发表于 最近 更新于 最近
作者 Administrator
49~64 分钟 阅读

作者:Dafang
日期:2026-03-23
标签:Mihomo · Docker · Ubuntu · 代理 · 宝塔面板


前言

Mihomo(原 Clash.Meta)是目前功能最强大的代理内核之一,支持 TUN 透明代理、多种协议(VLESS/VMess/Trojan/SS)、规则分流等高级特性。本文记录了在 Ubuntu Server 24.04 上通过 Docker Compose 完整部署 Mihomo 的全过程,包括订阅转换、Web 控制面板、以及通过宝塔面板实现订阅自动更新。


环境说明

项目

版本

操作系统

Ubuntu Server 24.04 LTS

Docker

最新版

Docker Compose

最新版(集成于 Docker)

面板

宝塔面板

网络

内网服务器(已关闭 UFW 防火墙)


一、创建目录结构

mkdir -p /www/dk_project/dk_app/dk_mihomo/config
cd /www/dk_project/dk_app/dk_mihomo

目录规划:

/www/dk_project/dk_app/dk_mihomo/
├── docker-compose.yml          # 服务编排文件
├── update_config.sh            # 订阅更新脚本
└── config/
    ├── config.yaml             # Mihomo 主配置(由订阅转换生成)
    └── metacubexd/             # Web UI Caddy 配置(自动生成)

二、获取订阅配置

机场提供的订阅链接通常返回 Base64 编码的节点列表,Mihomo 无法直接使用,需要通过订阅转换器转为 Clash/Mihomo 格式的 YAML。

方法:使用公共订阅转换器

SUBSCRIBE_URL="你的机场订阅链接"
ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$SUBSCRIBE_URL'))")

curl -L "https://api.v1.mk/sub?target=clash&url=${ENCODED}&insert=false" \
  -o /www/dk_project/dk_app/dk_mihomo/config/config.yaml

验证转换结果:

head -5 /www/dk_project/dk_app/dk_mihomo/config/config.yaml

正确的配置文件开头应该是标准 YAML 格式:

port: 7890
mixed-port: 7890
allow-lan: true
mode: rule
...

常用公共转换器:

  • https://api.v1.mk/sub?target=clash&url=<订阅链接>

  • https://sub.xeton.dev/sub?target=clash&url=<订阅链接>

如果某个转换器返回 520 等错误,换另一个即可。


三、编写 docker-compose.yml

# /www/dk_project/dk_app/dk_mihomo/docker-compose.yml

services:
  mihomo:
    container_name: mihomo
    image: metacubex/mihomo:latest
    restart: always
    pid: host                        # 共享宿主机 PID,TUN 模式感知进程
    ipc: host                        # 共享宿主机 IPC
    network_mode: host               # 使用宿主机网络栈,TUN 模式必须
    cap_add:
      - ALL                          # 赋予完整权限(含 NET_ADMIN、NET_RAW)
    security_opt:
      - apparmor=unconfined          # 关闭 Ubuntu AppArmor 限制
    volumes:
      - ./config:/root/.config/mihomo
      - /dev/net/tun:/dev/net/tun    # 挂载 TUN 虚拟网卡设备
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro

  metacubexd:
    container_name: metacubexd
    image: ghcr.io/metacubex/metacubexd
    restart: always
    network_mode: bridge
    ports:
      - '9097:80'                    # 浏览器访问 http://服务器IP:9097
    volumes:
      - ./config/metacubexd:/config/caddy
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro

关键配置项说明

配置项

说明

pid: host

容器与宿主机共享 PID 命名空间,TUN 透明代理感知进程必需

ipc: host

共享进程间通信命名空间,配合 pid: host 使用

network_mode: host

直接使用宿主机网络栈,TUN 模式接管流量必需

cap_add: ALL

赋予所有 Linux capabilities,避免 TUN 权限不足报错

apparmor=unconfined

Ubuntu 默认启用 AppArmor 会拦截 TUN 操作,必须关闭

/dev/net/tun

TUN 虚拟网卡设备,Mihomo 通过它创建虚拟接口接管流量

metacubexd: bridge

Web UI 无需接管网络,用桥接模式更安全


四、启动服务

cd /www/dk_project/dk_app/dk_mihomo

# 拉取镜像并启动
docker compose up -d

# 查看启动日志
docker compose logs -f mihomo

查看服务状态:

docker compose ps

五、验证代理可用性

# 测试 HTTP 代理
curl -x http://127.0.0.1:7890 https://www.google.com -I

成功响应示例:

HTTP/1.1 200 Connection established
HTTP/2 200
...
server: gws

看到 Connection established 和 HTTP/2 200 即表示代理正常工作。


六、访问 Web 控制面板

浏览器打开:

http://服务器IP:9097

在面板中填写:

  • API 地址:http://服务器IP:9090

  • 密码:config.yaml 中 secret 字段的值

面板功能包括:节点切换、延迟测试、实时流量、规则查看等。


七、宝塔面板计划任务配置

三个自动更新任务均采用直接在宝塔计划任务脚本框中填写脚本内容的方式,无需创建外部 sh 文件,管理更集中。所有脚本输出到 stdout,宝塔日志界面可直接查看。

注意:宝塔计划任务(cron)不会自动加载 /etc/profile.d/,所以脚本中凡是依赖特定命令路径的地方,均使用绝对路径,避免 command not found。

进入 宝塔面板 → 计划任务 → 添加任务,依次添加以下三个任务。


7.1 任务一:Mihomo 订阅更新

字段

填写内容

任务类型

Shell脚本

任务名称

mihomo订阅更新

执行周期

每天 03:00

脚本内容:

#!/bin/bash

export http_proxy=http://127.0.0.1:7890
export https_proxy=http://127.0.0.1:7890

SUBSCRIBE_URL="你的机场订阅链接"
CONFIG_PATH="/www/dk_project/dk_app/dk_mihomo/config/config.yaml"
ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$SUBSCRIBE_URL'))")

echo "========================================"
echo "  Mihomo 订阅更新"
echo "  $(date '+%Y-%m-%d %H:%M:%S')"
echo "========================================"

echo "[$(date '+%Y-%m-%d %H:%M:%S')] 开始拉取订阅..."
curl -sL "https://api.v1.mk/sub?target=clash&url=${ENCODED}&insert=false" \
  -o $CONFIG_PATH

if [ $? -eq 0 ] && [ -s $CONFIG_PATH ]; then
    NODE_COUNT=$(grep -c "^  - name:" $CONFIG_PATH 2>/dev/null || echo "未知")
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] 订阅拉取成功,节点数:${NODE_COUNT}"
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] 正在重启 mihomo..."
    docker restart mihomo
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] ✓ 完成"
else
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] ✗ 订阅拉取失败,保留原配置"
    exit 1
fi

日志输出示例:

========================================
  Mihomo 订阅更新
  2026-03-23 03:00:00
========================================
[2026-03-23 03:00:01] 开始拉取订阅...
[2026-03-23 03:00:03] 订阅拉取成功,节点数:32
[2026-03-23 03:00:03] 正在重启 mihomo...
[2026-03-23 03:00:05] ✓ 完成

7.2 任务二:Claude Code 更新

Claude Code 安装在 /root/.local/bin/claude(通过 npm 全局安装,路径不在宝塔 Node.js 目录下)。

字段

填写内容

任务类型

Shell脚本

任务名称

Claude Code更新

执行周期

每天 04:00

脚本内容:

#!/bin/bash

export http_proxy=http://127.0.0.1:7890
export https_proxy=http://127.0.0.1:7890

# Claude Code 实际路径(通过 which claude 确认)
CLAUDE_BIN=/root/.local/bin/claude

echo "========================================"
echo "  Claude Code 更新"
echo "  $(date '+%Y-%m-%d %H:%M:%S')"
echo "========================================"

if [ ! -f "$CLAUDE_BIN" ]; then
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] ✗ 找不到 claude 命令:${CLAUDE_BIN}"
    exit 1
fi

OLD_VER=$($CLAUDE_BIN --version 2>/dev/null || echo "未知")
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 当前版本:${OLD_VER}"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 开始更新..."

$CLAUDE_BIN update
EXIT_CODE=$?
NEW_VER=$($CLAUDE_BIN --version 2>/dev/null || echo "未知")

if [ $EXIT_CODE -eq 0 ]; then
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] ✓ 更新完成,当前版本:${NEW_VER}"
else
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] ✗ 更新失败(exit code: ${EXIT_CODE}),当前版本:${OLD_VER}"
    exit 1
fi

日志输出示例:

========================================
  Claude Code 更新
  2026-03-23 04:00:00
========================================
[2026-03-23 04:00:01] 当前版本:2.1.81 (Claude Code)
[2026-03-23 04:00:02] 开始更新...
Claude Code is up to date (2.1.81)
[2026-03-23 04:00:15] ✓ 更新完成,当前版本:2.1.81 (Claude Code)

7.3 任务三:OpenClaw 更新

OpenClaw 通过宝塔 Node.js 环境安装,路径为 /www/server/nodejs/v24.14.0/bin/openclaw。

字段

填写内容

任务类型

Shell脚本

任务名称

OpenClaw更新

执行周期

每天 04:10

脚本内容:

#!/bin/bash

export http_proxy=http://127.0.0.1:7890
export https_proxy=http://127.0.0.1:7890

# 宝塔 Node.js 路径(openclaw 依赖 node 运行时)
export NODE_HOME=/www/server/nodejs/v24.14.0
export PATH=$NODE_HOME/bin:$PATH
OPENCLAW_BIN=/www/server/nodejs/v24.14.0/bin/openclaw

echo "========================================"
echo "  OpenClaw 更新"
echo "  $(date '+%Y-%m-%d %H:%M:%S')"
echo "========================================"

if [ ! -f "$OPENCLAW_BIN" ]; then
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] ✗ 找不到 openclaw 命令:${OPENCLAW_BIN}"
    exit 1
fi

OLD_VER=$($OPENCLAW_BIN --version 2>/dev/null || echo "未知")
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 当前版本:${OLD_VER}"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 开始更新..."

$OPENCLAW_BIN update
EXIT_CODE=$?
NEW_VER=$($OPENCLAW_BIN --version 2>/dev/null || echo "未知")

if [ $EXIT_CODE -eq 0 ]; then
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] ✓ 更新完成,当前版本:${NEW_VER}"
else
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] ✗ 更新失败(exit code: ${EXIT_CODE}),当前版本:${OLD_VER}"
    exit 1
fi

日志输出示例:

========================================
  OpenClaw 更新
  2026-03-23 04:10:00
========================================
[2026-03-23 04:10:01] 当前版本:0.8.1
[2026-03-23 04:10:02] 开始更新...
[2026-03-23 04:10:20] ✓ 更新完成,当前版本:0.8.2

三个任务执行时间错开 10 分钟,避免同时请求网络资源互相干扰,也方便在日志里区分各任务的输出。


八、宿主机代理环境全局配置

Mihomo 启动后,宿主机本身的各个工具需要分别配置才能走代理,原因是不同工具读取代理的方式不同,没有统一的全局入口。

8.1 Shell 环境变量(终端 curl / wget / git 等)

写入 /etc/profile.d/ 使所有用户登录终端自动生效:

cat > /etc/profile.d/proxy.sh << 'EOF'
export http_proxy=http://127.0.0.1:7890
export https_proxy=http://127.0.0.1:7890
export HTTP_PROXY=http://127.0.0.1:7890
export HTTPS_PROXY=http://127.0.0.1:7890
export no_proxy=localhost,127.0.0.1,192.168.0.0/16,10.0.0.0/8
EOF

# 当前终端立即生效
source /etc/profile.d/proxy.sh

# 验证
curl https://www.google.com -I --max-time 5

注意:/etc/profile.d/ 只对交互式登录 Shell 生效,cron 计划任务、systemd 服务均不会自动读取。

若宝塔计划任务脚本需要走代理,在脚本头部手动加上:

#!/bin/bash
export http_proxy=http://127.0.0.1:7890
export https_proxy=http://127.0.0.1:7890
# ... 后续命令

8.2 Docker Daemon 代理(docker pull 拉取镜像)

Docker 守护进程有独立的代理配置,Shell 环境变量对其无效:

mkdir -p /etc/systemd/system/docker.service.d

cat > /etc/systemd/system/docker.service.d/proxy.conf << 'EOF'
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:7890"
Environment="HTTPS_PROXY=http://127.0.0.1:7890"
Environment="NO_PROXY=localhost,127.0.0.1,192.168.0.0/16,10.0.0.0/8"
EOF

# 重载配置并重启 Docker
systemctl daemon-reload
systemctl restart docker

# 验证
docker info | grep -i proxy

成功后 docker info 应显示:

HTTP Proxy: http://127.0.0.1:7890
HTTPS Proxy: http://127.0.0.1:7890
No Proxy: localhost,127.0.0.1,192.168.0.0/16,10.0.0.0/8

8.3 npm 代理

npm 有独立的代理配置,与系统环境变量无关:

# 设置代理
npm config set proxy http://127.0.0.1:7890
npm config set https-proxy http://127.0.0.1:7890

# 验证
npm config get proxy
npm config get https-proxy

# 测试(安装一个小包试试)
npm install -g npm@latest

如需取消 npm 代理(切换回直连或镜像源):

npm config delete proxy
npm config delete https-proxy

# 国内可改用淘宝镜像替代代理
npm config set registry https://registry.npmmirror.com

npm 代理与 registry 镜像源可以独立配置,互不影响。代理优先级高于 registry。


8.4 各工具代理生效范围汇总

工具

配置方式

说明

curl / wget / git

/etc/profile.d/proxy.sh 环境变量

仅交互式 Shell

宝塔计划任务脚本

脚本头部手动 export

cron 不读 profile

docker pull

/etc/systemd/system/docker.service.d/proxy.conf

需重启 Docker

容器内部

docker run -e http_proxy=... 或 compose env

独立设置

npm

npm config set proxy

独立配置

pip

pip install --proxy http://127.0.0.1:7890

或设置环境变量


8.5 局域网其他设备使用代理

Mihomo 配置中 allow-lan: true 开启后,局域网内其他设备可直接接入:

# 其他 Linux / macOS / WSL 机器
export http_proxy=http://服务器IP:7890
export https_proxy=http://服务器IP:7890
export no_proxy=localhost,127.0.0.1,192.168.0.0/16,10.0.0.0/8

Windows 在「设置 → 网络和 Internet → 代理」中填写服务器 IP 和端口 7890 即可。


九、常用管理命令

# 查看实时日志
docker compose logs -f mihomo

# 重启服务
docker compose restart mihomo

# 热重载配置(不重启容器,需要 config.yaml 中设置了 secret)
curl -X PUT http://127.0.0.1:9090/configs \
  -H "Authorization: Bearer 你的secret" \
  -H "Content-Type: application/json" \
  -d '{"path": "/root/.config/mihomo/config.yaml"}'

# 更新镜像
docker compose pull && docker compose up -d

# 停止服务
docker compose down

总结

整个部署流程的关键点:

  1. 订阅转换:机场 Base64 订阅需要经过转换器转为 Clash YAML 格式

  2. TUN 模式权限:pid/ipc: host + cap_add: ALL + apparmor=unconfined 三者缺一不可

  3. Web UI 分离部署:metacubexd 用 bridge 网络单独运行,通过 API 端口连接 Mihomo

  4. 自动更新:宝塔计划任务 + Shell 脚本,日志直接输出到 stdout 方便面板查看

  5. 代理配置各自独立:Shell 环境变量 / Docker Daemon / npm 需要分别配置,没有统一入口

整套方案在内网服务器上稳定运行,局域网内所有设备均可通过 7890 端口使用代理。

许可协议: 
分享

相关文章

下一篇

上一篇

FastTunnel v2 内网穿透 Docker 部署完整指南(服务端 + 客户端)

最近更新

  • Ubuntu Server 24.04 使用 Docker Compose 部署 Mihomo 完整指南
  • FastTunnel v2 内网穿透 Docker 部署完整指南(服务端 + 客户端)
  • Windows 10 LTSC 上用 WSL + mihomo 实现 Claude Code Agent Teams 分屏模式完整指南
  • OpenClaw 完整安装与使用指南:零成本打造全能 AI 助理
  • Debian 13 虚拟机安装与配置完全指南(Parallels / VMware 双平台)

热门标签

MCP 并发编程 通义千问 代码审查 版本对比 数字人 开发效率 DevOps 结构化并发 永久投资组合

目录

©2026 范伟彬个人网. 保留部分权利。

使用 Halo 主题 Chirpy