Clash Meta Docker 部署:Compose 与镜像更新完整步骤
许多读者已经在 VPS、家用服务器或 NAS 上使用 Docker 管理其它服务,自然希望把 Clash Meta(常见发行名为 Mihomo 内核)也纳入同一套声明式、可版本化的运维流程:用 Docker Compose 固定镜像标签、用卷挂载保留配置与订阅持久化,升级时只需 pull 与滚动重建,而不是在裸机上反复手工替换二进制。本文与站内《Clash Linux 无图形 + systemd》专题并列——那边适合「不想装 Docker、直接跑可执行文件」的路径;这里专注容器化 headless:镜像选择、目录挂载、端口与网络、外部控制器与安全边界,以及镜像更新与回滚的实操顺序。
为什么要在服务器上用 Docker 跑 Clash Meta
在纯 Linux 上直接下载二进制并由 systemd 托管,优点是链路短、排障直观;而 Docker 的价值在于交付物一致:同一台机器上开发、测试与生产可以用同一份 compose.yaml 复现,依赖项(libc、时区、工作目录)被镜像边界封装,升级时替换的是镜像 ID而不是散落各处的文件。对 NAS 或面板类环境尤为友好——很多系统已经内置 Compose 或图形化堆栈管理,你只需多一个服务定义。
搜索意图上,「Clash Meta Docker」与「Linux systemd」是两条常见路径:前者强调编排与隔离,后者强调最小依赖与本机集成。若你已有 Compose 仓库管理其它容器,把 Meta 内核放进同一仓库,比在宿主机再维护一套解压路径与权限位更省心。反之,若机器上根本没有 Docker、也不打算引入,请直接参考 systemd 专题,不必为了「赶时髦」硬上容器。
心智模型
把 Compose 文件看成可审计的部署合同:镜像名与标签、卷、端口、重启策略写清楚后,换机器或灾难恢复时按合同重建即可;配置与订阅则应落在卷里,而不是写进镜像层。
镜像与标签:固定版本,避免「latest 漂移」
社区常用的上游镜像命名会随时间调整,但工程原则不变:生产环境避免无标签的 :latest 作为唯一依据。请在镜像仓库页面核对官方或维护者推荐的 tag(例如带版本号或日期的稳定标签),在 compose.yaml 中显式写出该标签,并把你的 Git 仓库或配置管理里记下「当前运行版本」。这样当上游发布安全修复时,你可以有意识地执行升级,而不是在某次宿主机重启后突然发现行为变化。
若你需要尝试新特性分支,可为测试栈单独建一个 Compose 项目目录,使用不同容器名与端口,避免与生产实例抢配置文件或端口。验证通过后再 bump 生产标签,是容器场景里最常见的金丝雀做法。
Docker Compose 骨架:服务、重启策略与环境
下面是一份示意性的 compose.yaml,用于说明常见字段;请根据你所选镜像文档调整镜像名、默认配置路径、用户 ID等细节。多数 Mihomo 镜像会把可读写的配置目录放在容器用户家目录下的 .config/mihomo 一类路径——挂载宿主机目录到该路径后,容器重建不会丢失 config.yaml、GeoSite 缓存以及 proxy-providers 下载下来的订阅快照。
# Illustrative compose — replace image tag and paths per upstream docs
services:
mihomo:
image: metacubex/mihomo:v1.19.0
container_name: clash-meta
restart: unless-stopped
environment:
- TZ=Asia/Shanghai
volumes:
- ./mihomo-config:/root/.config/mihomo
ports:
- "7890:7890"
- "7891:7891"
- "9090:9090"
ports 中映射哪些端口取决于你的 config.yaml:常见包括 mixed-port(HTTP/SOCKS 合一)、单独的 SOCKS、以及 external-controller(REST API,用于无图形 headless 场景下的健康检查与热加载)。不要把未使用的管理端口暴露到公网——见下文安全段落。
落地顺序建议
- 在宿主机准备空目录与最小可用的
config.yaml(可先只含端口与控制器开关)。 - 启动容器后,确认日志无报错、映射端口在宿主机可访问。
- 再接入
proxy-providers或订阅 URL,观察卷内是否出现缓存文件。 - 最后才加防火墙、反代或仅监听内网的约束。
卷挂载与订阅持久化
订阅持久化在容器场景里有两层含义:一是你的规则与 provider 定义(写在 YAML 里,应纳入 Git 或备份);二是内核按 interval 拉取的远程节点快照(通常落在数据目录下的缓存文件)。只要把这些路径放在绑定挂载的宿主机目录中,执行 docker compose down 再 up 不会清空节点列表。
若你使用 proxy-providers 的 path 指向卷内相对路径,请确保目录权限与容器内运行用户一致——权限不匹配时常见症状是「能启动但无法写缓存、订阅始终为空」。NAS 上若使用图形化 Docker 面板,注意其默认卷路径与备份策略是否覆盖你的配置目录。
| 内容 | 建议 |
|---|---|
config.yaml |
纳入版本控制或定期导出;敏感 token 用环境变量或密钥管理注入更佳 |
| GeoIP / GeoSite 数据库 | 可随镜像更新,也可挂载固定文件以便离线环境 |
| provider 缓存 | 放在同一挂载卷,重建容器后不重新全量下载(视上游策略) |
端口映射与网络模式:bridge 还是 host
默认 bridge 网络配合 ports 映射对大多数「本机或其它容器访问 Clash」的场景足够:宿主机上的其它进程通过 127.0.0.1:端口 或局域网 IP 访问映射口即可。若你需要让 Clash 直接参与宿主机网络命名空间(例如某些 TUN 或透明代理场景),才会考虑 network_mode: host——这会绕开 Docker 的端口映射模型,排错方式也与 bridge 不同。
在无图形 headless 服务器上,常见拓扑是:Clash 只对内网或本机开放 mixed-port,由同机上的浏览器自动化、下载器或其它容器设置 http_proxy / HTTPS_PROXY 环境变量指向该端口。若同一主机还有反向代理(如 Nginx/Caddy),务必分清「入站 Web」与「出站 Clash」的端口,避免配置混淆。
容器内 TUN 与特权
若你计划在容器里启用 TUN 模式,通常涉及额外内核能力或 privileged,且与宿主机网络栈强耦合。多数「仅作 HTTP/SOCKS 出站代理」的 headless 部署不需要在容器内开 TUN;若确有需要,请先阅读镜像文档并在测试环境验证,再决定是否在安全边界上接受更高权限。
无图形环境与 external-controller
Headless 意味着没有桌面面板,运维入口主要是日志与外部控制器 API。在 config.yaml 中开启 external-controller 后,你可以用上游文档中的 REST 接口做配置重载、延迟测试等。务必设置访问密钥(若内核支持),并仅将端口绑定到可信网络接口或通过 SSH 隧道访问——暴露在公网的未鉴权控制器是真实事故来源。监听地址、secret、宿主机 ports 绑定与防火墙的逐步做法,见专题 《Clash Meta Web 面板远程访问:bind-address 与 secret 加固》。
与 DNS、fake-ip 相关的异常在容器里同样会出现:若出现「日志有连接但业务不通」,可对照 《DNS 泄漏与 fake-ip 排查》 逐项缩小范围,每次只改一个变量,避免同时调整镜像版本与 DNS 配置。
镜像更新、重建与回滚
推荐的升级节奏是:先读上游 release note,再在维护窗口执行 docker compose pull,随后 docker compose up -d 触发用新镜像重建容器。绑定卷中的配置与缓存应保留不变。若升级后行为异常,回滚只需把 compose 中的标签改回上一已知良好版本,再次 pull(若本地已无该层)并 up -d。
为了可重复部署,请把当时使用的镜像 digest 或标签记在运维记录里;遇到「同标签被覆盖推送」的极端情况时,digest 能帮你对齐真实二进制。对关键生产环境,部分团队会在私有仓库中镜像固化一层,进一步减少上游变更的突发性。
与 systemd 裸机方案如何二选一
站内《Clash Linux 无图形环境部署》侧重二进制 + systemd + 定时更新订阅,适合不想引入容器运行时的情况。本文侧重Docker Compose + 卷 + 镜像生命周期。两者在「配置写法、规则与 DNS 原理」上相通;差别主要在运维接口:你更熟悉 systemctl 还是 docker compose、备份与监控是否已围绕容器搭建。可以同时在实验室各跑一份,用相同 config.yaml 对比启动日志与资源占用,再决定生产选型。
常见问题
重建容器后节点列表为空?
检查卷是否仍挂载到正确路径、proxy-providers 的 path 是否指向卷内可写位置,以及容器日志是否有下载失败或 TLS 错误。
提示端口已被占用?
确认宿主机或其它 Compose 项目未占用同一映射端口;或修改 compose 左侧(宿主机侧)端口号,并同步更新依赖该端口的客户端配置。
定时任务或证书时间异常?
为容器设置正确的 TZ 环境变量,并确认宿主机系统时间已同步(NTP)。时间漂移会导致 HTTPS 握手与订阅更新间歇性失败。
下一步与客户端
把 Meta 内核放进 Docker 只是交付形态之一;规则质量、节点选择与 DNS 仍决定实际体验。完成 Compose 部署后,建议在可信终端上验证 mixed-port 连通,再逐步放开局域网访问或自动化任务。