去年把家里那台退役的小主机重新装起来跑自建服务之后我就一直在琢磨一件事怎么让手机、笔记本、办公室的台式机还有放在另一个地方的备用机像坐在同一个机房里一样互相访问。试过端口映射运营商给的是内网地址白折腾试过自建隧道工具配置文档看得脑仁疼改一次网络环境就得返工一次。后来把目光落到 ZeroTier 上用了一阵子觉得思路对但每次换机器都要重新装一遍、配一遍升级还得盯着麻烦。于是就有了这次docker搭建zerotier的折腾——把组网客户端整个塞进容器里配置文件挂出来换机只拷一个目录升级只换一个镜像标签。这篇就把我这一路踩过的坑、参数怎么算、命令怎么写一次性摊开讲清楚。适合三类人看手里有 NAS 或自建服务想在外网访问的有多个地点设备要互联但不想动路由器的以及已经会用 Docker、想把网络组件也容器化统一管理的。1. 为什么把 ZeroTier 塞进 Docker 跑1.1 裸机安装和容器化部署的真实差异先说结论如果你只有一台机器、这辈子不打算换系统裸机装最省事。但只要设备超过两台或者你有重装系统后要恢复环境的强迫症容器化就是更划算的选择。裸机安装的方式通常是跑一个官方脚本装完之后会在系统里注册守护进程、写 systemd unit、往/var/lib/zerotier-one塞身份文件、在网卡列表里多出一个虚拟接口。这套东西散落在系统各处卸载不干净会留残渣升级时如果配置文件格式变了还得手工迁移。更要命的是很多轻量系统比如某些精简版的 NAS 系统、容器优化型系统根本没有完整的 systemd脚本跑一半就报错。容器化之后情况变成所有东西都在一个目录里镜像换掉就是升级目录删掉就是卸载宿主系统只多了一个/dev/net/tun的依赖和几条防火墙规则。我做过一次对比测试同一台机器上两种方式各跑一遍差异大致是这样对比项裸机安装Docker 容器化安装复杂度一条脚本但依赖 systemd一条 docker run依赖 tun 设备升级方式重跑脚本或包管理器换镜像标签重启容器配置迁移手工备份/var/lib/zerotier-one挂载目录直接拷走卸载残留可能留下 unit 文件和路由删容器删目录即可多实例共存基本不可能换容器名和端口即可对宿主系统侵入较深较浅需要说明的是容器化不是没有代价。容器里跑网络组件最大的坑在于它需要修改宿主机的网络栈而容器的默认隔离恰好把这块挡住了。这就引出了下一个必须想清楚的问题网络模式怎么选。1.2 网络模式选型host、macvlan 还是桥接ZeroTier 的工作方式是在本机创建一块虚拟网卡名字一般是zt开头的一串字符然后通过这块网卡收发封装后的数据包。这意味着它必须能创建网络接口、修改路由表、操作 iptables 规则这三件事在容器里都需要额外授权。桥接模式是最先被排除的。默认 bridge 网络下容器有自己独立的网络命名空间它创建的虚拟网卡只存在于容器内部宿主机和局域网里的其他设备根本看不见等于组了个孤岛。你在容器里ping得通对端宿主机却进不去这个现象我第一次遇到时排查了快两个小时。macvlan 模式能让容器在网络层看起来像一台独立设备有自己的 MAC 地址能从上级路由器拿地址。理论可行但实际用起来有两个麻烦一是很多家用路由器对 macvlan 支持不好二是宿主机会和容器互相看不见这是 macvlan 的已知特性排查问题时非常别扭。最后我选的是host 网络模式。容器直接共享宿主机的网络命名空间它创建的虚拟网卡就等于建在宿主机上路由、转发、iptables 全部直接生效没有中间层。代价是端口不能自定义映射因为压根没有映射这回事ZeroTier 默认用的 UDP 9993 端口会和宿主上已有的实例冲突。这个冲突反倒帮我养成了一个好习惯部署前先查端口占用。注意host 模式下容器不再有独立的网络隔离镜像里的其他服务也会直接占用宿主端口。如果你打算在一个容器里塞多个服务务必先规划好端口。1.3 整体结构长什么样把整个方案拆开看一共四层最底下是宿主机的物理网卡和内核转发能力往上是容器里的 ZeroTier 客户端负责加密、封装、维持连接再往上是虚拟网段所有设备在这个网段里各占一个地址最上面才是你真正要访问的服务比如 NAS 的管理页面、代码仓库、监控面板。数据包的走向大致是你的笔记本发出一个目标地址为10.147.17.5的包本机 ZeroTier 虚拟网卡接管加密封装成 UDP 包通过物理网卡发出去对端收到后解封装还原成原始包交给目标服务。整个过程对应用层完全透明你在浏览器里输的就是那个虚拟地址。这套结构的关键在于地址规划。虚拟网段和你的物理网段如果撞了路由就会打架表现为有时候通有时候不通这种间歇性故障最折磨人。我在第 3 章会给出一套具体的规划方法和计算过程先把这块搞清楚后面能少走一大半弯路。2. 动手前的环境准备与概念扫盲2.1 主机环境的硬性检查清单动手前有几项必须确认缺一项后面就会卡住。第一是内核的 TUN/TAP 支持。ZeroTier 依赖这个虚拟网络设备来收发数据。绝大多数发行版默认编译进去了但部分精简系统会裁掉。检查命令很简单ls -l /dev/net/tun正常应该输出类似crw-rw-rw- 1 root root 10, 200 ... /dev/net/tun的内容。如果提示没有那个文件或目录说明设备节点没创建需要手工补上mkdir -p /dev/net mknod /dev/net/tun c 10 200 chmod 666 /dev/net/tun这里的10, 200是 TUN 设备固定的主次设备号不是随便编的。写成别的数字设备能创建出来但打开会失败症状是容器日志里反复打印cannot open tun device。第二是 IP 转发。如果这台机器要充当网关让虚拟网段里的设备能访问它所在的物理局域网必须打开转发sysctl net.ipv4.ip_forward返回 0 就是没开。临时打开用sysctl -w net.ipv4.ip_forward1永久生效要写进/etc/sysctl.conf或/etc/sysctl.d/下的配置文件。只做点对点访问、不需要跨网段转发的场景这项可以跳过。第三是端口占用。host 模式下 ZeroTier 会占用 UDP 9993。部署前查一下ss -ulnp | grep 9993有输出就说明被占了要么停掉占用的进程要么在容器启动时通过环境变量或配置文件改端口。改端口的话对端也得知道你的新端口配置会变复杂所以我一般选择让占用方让路。第四是 Docker 本身的版本。用docker version看建议 20.10 以上--device和--cap-add这些参数在旧版本上行为有差异尤其是 rootless 模式下很多网络相关的能力直接不可用。如果你用的是 rootless Docker这篇的方案跑不通得换回 root 模式或者用其他方式。2.2 三个必须搞懂的核心概念概念不清楚后面看命令就是一串字符出问题也不知道从哪查起。网络 IDNetwork ID一串 16 位十六进制字符代表一个虚拟局域网。创建之后所有想加入的设备都填这串东西。它不是密钥泄露了不会直接导致别人能进来因为还有授权环节。但仍然不建议到处贴属于知道的人越少越好的信息。成员与授权Member / Authorize每台设备加入网络后处于待授权状态会在管理后台的成员列表里出现显示一个 10 位的节点地址。管理员勾选授权之后设备才真正拿到 IP、才能通信。这个设计是整个方案的安全基础——光有网络 ID 进不来必须管理员点头。我一般还会把自动授权关掉宁可每次手工点一下。托管路由Managed Route这是让虚拟网段和物理网段打通的关键。举个例子你家里有个 NAS地址是192.168.50.10你想在外面直接访问它而不是先连到某台跳板机再转。做法是在网络配置里加一条路由目标192.168.50.0/24经由10.147.17.5也就是家里那台跑 ZeroTier 的机器。这样其他设备访问192.168.50.x时会把包交给10.147.17.5由它转发。这三个概念串起来就是完整链路网络 ID 决定进哪个圈子授权决定能不能进托管路由决定进去之后能摸到哪些网段。想明白这层后面的配置就是填空题。2.3 内核转发与 NAT 的前置配置托管路由要生效光在后台加一条规则是不够的承载转发的那台机器下文叫它网关节点必须真的会转发。前面已经打开了ip_forward接下来还要处理地址转换。原因是这样虚拟网段10.147.17.0/24是你的私有网段NAS 所在的192.168.50.0/24是另一个私有网段NAS 本身不认识10.147.17.x它回包时会把目标地址当成不存在直接丢弃。解决办法是让网关节点做一次源地址转换SNAT把来自虚拟网段的包伪装成网关自己的地址发出去回包再由网关还原。命令是iptables -t nat -A POSTROUTING -s 10.147.17.0/24 -o eth0 -j MASQUERADE这里的eth0要换成你宿主机的实际出口网卡名用ip route | grep default可以看到。-s 10.147.17.0/24是限制只对这个网段做转换别写成0.0.0.0/0否则会把你所有的出站流量都改写一遍容易引发其他服务的异常。规则写完记得持久化。不同的发行版工具不一样常见的做法是iptables-save /etc/iptables/rules.v4或者在netfilter-persistent里保存。不持久化的话机器一重启规则就没了症状是重启前好好的重启后只能 ping 通网关访问不了内网服务。提示如果你用的是 Docker 管理的防火墙链比如某些系统会把规则插到 DOCKER 链里手工加的规则可能被 Docker 重启时清掉。这种情况建议把规则写进 systemd 的 ExecStartPre或者用 compose 的post_start钩子重新加一遍。3. 从零把 ZeroTier 跑进容器的完整实操3.1 拉镜像与第一次启动镜像来源有两类官方维护的和社区打包的。官方镜像体积小、更新跟得紧优先选它。社区镜像有时会额外塞进一些便利脚本但对版本对应关系要求高出问题不好定位。拉取docker pull zerotier/zerotier:latest首次启动我建议先用前台模式跑一次直接看日志确认没有报错再转后台。前台模式docker run --rm -it \ --name zt-test \ --network host \ --cap-add NET_ADMIN \ --cap-add SYS_ADMIN \ --device /dev/net/tun \ zerotier/zerotier:latest几个参数逐个说清楚因为少一个都跑不起来--network host前面分析过为了让虚拟网卡直接建在宿主上。--cap-add NET_ADMIN允许创建网络接口、修改路由和防火墙。这是硬性要求。--cap-add SYS_ADMIN一部分系统在创建 TUN 设备时需要这个能力不给的话会在初始化阶段卡住。安全性上这属于比较宽的能力所以更推荐的做法是配合--security-opt no-new-privileges使用缩小影响面。--device /dev/net/tun把宿主机的 TUN 设备映射进容器。启动后日志里会出现节点地址和版本信息。如果看到类似starting...之后就没了动静或者直接退出去第 4 章看排查部分。确认能跑通之后换成后台常驻并且把数据目录挂出来mkdir -p /opt/zerotier/data docker run -d \ --name zerotier \ --restart unless-stopped \ --network host \ --cap-add NET_ADMIN \ --cap-add SYS_ADMIN \ --device /dev/net/tun \ -v /opt/zerotier/data:/var/lib/zerotier-one \ zerotier/zerotier:latest挂载点的右侧路径不要改这是客户端约定的数据目录里面存着身份密钥、网络配置缓存、对端信息。左侧路径随你我习惯放在/opt下面方便统一备份。3.2 加入网络与后台授权数据目录挂好之后就可以加入了。先拿到网络 ID然后执行docker exec zerotier zerotier-cli join 你的网络ID返回200 join OK就说明请求发出去了但注意这只代表请求发了不代表已经能用。此时节点处于待授权状态在管理后台的成员列表里会看到一条新记录显示节点地址、虚拟 IP通常是空的或者显示为待分配、以及一个未勾选的授权框。勾选授权之后回到命令行查状态docker exec zerotier zerotier-cli listnetworks输出是一行表格几个字段要重点看字段含义正常值网络 ID你加入的网络与你填的一致状态连接状态OK类型网络类型PRIVATE 或 PUBLIC设备名虚拟网卡名zt 开头的字符串分配地址拿到的虚拟 IP网段内的某个地址状态位端口与中转状态类似OK PRIVATE如果分配地址这一列是空的基本就是没授权或者授权没生效。后台勾选后一般几秒内会推下来如果超过一分钟还是空的先确认是不是勾错了节点同名设备多了容易点错再确认网络类型是不是 PRIVATE——PRIVATE 网络必须授权PUBLIC 网络加入即可用。拿到地址之后先在本机自测ping -c 3 分配到的虚拟IP能通说明虚拟网卡工作正常。注意这里 ping 自己的虚拟 IP 走的是本机回环只能证明接口起来了不能证明组网通了。真正验证要拿另一台设备来 ping。3.3 网段规划与路由配置含参数计算这一步是整套方案里最容易出错的地方我单独拿一节讲透。先做地址规划。ZeroTier 默认会给网络分配一个网段常见的是10.147.17.0/24这一段的变形。如果你的物理局域网也是10.x开头撞车概率很高。判断方法看宿主机的路由表ip route里出现过的网段虚拟网段就要避开。假设我的环境是家庭物理网段192.168.50.0/24网关192.168.50.1NAS 地址192.168.50.10办公物理网段192.168.60.0/24网关192.168.60.1代码服务器192.168.60.20虚拟网段10.147.17.0/24网段能不能用算一下就知道。/24意味着前 24 位是网络位后 8 位是主机位可用地址是 2^8 - 2 254 个去掉网络地址.0和广播地址.255。对个人或小团队来说完全够用。如果设备超过 254 台改成/23可用地址变成 2^9 - 2 510 个。这个计算不用背记住可用数 2 的主机位数次方减 2就行。虚拟 IP 的分配我建议手工指定而不是自动。原因是自动分配虽然省事但设备一多、名字一乱你根本记不住哪个地址是哪台机器排查问题时全靠翻后台。手工指定之后我给每台设备编了号10.147.17.1是家里的网关节点.2是办公室的网关节点.10往后是笔记本、手机、平板这些终端。看一眼地址就知道是谁。再配托管路由。在管理后台的网络设置里找到路由配置区域加两条目标网段经由说明192.168.50.0/2410.147.17.1回家里的局域网192.168.60.0/2410.147.17.2回办公室的局域网这里的经由填的是网关节点在虚拟网段里的地址。添加时通常还有一个广播选项含义是把这条路由推送给网络里所有成员让它们自动加到本机路由表。个人使用建议打开省得每台设备手工加路由。配完之后在两台网关节点的宿主机上分别执行 NAT 规则就是 2.3 节那条命令然后把流量打通。验证方法是找一台不在任何物理局域网内的设备比如手机开热点连笔记本去 ping NAS 的物理地址ping -c 3 192.168.50.10通说明整条链路搭好了。不通的话按这个顺序查先 ping 网关节点虚拟地址确认组网本身通再查网关节点的ip_forward是不是 1再查 NAT 规则在不在最后查目标设备的防火墙是不是把来源网段挡了。提示目标设备比如 NAS自己的防火墙经常忘。它看到的来源地址是网关的物理地址因为做了 SNAT所以只需要放行网关 IP 就行不用放行整个虚拟网段。这是个挺好用的收窄权限的口子。MTU 也需要算一下。ZeroTier 的虚拟网卡默认 MTU 是 2800看着很大但实际链路要经过物理网卡一般 1500封装封装头会占掉一部分空间。如果虚拟 MTU 设得比链路能承载的还大大包会被丢弃症状特别典型小文件能传、网页能开、但视频卡顿、大文件传输断、ping小包通而ping -s 1400不通。我一般把虚拟网卡 MTU 调成 1400留出足够余量。改法是进容器执行docker exec zerotier ip link set dev zt设备名 mtu 1400设备名从listnetworks的输出里拿。这条命令重启后失效要持久化得写进网络配置或者用一个启动脚本重新执行。实测下来 1400 在大多数家用宽带上够用如果还是丢包往下降到 1380 试试。3.4 用 compose 把配置固化成文件手工敲docker run的问题在于过两个月你自己都想不起来当时加了哪些参数。用 compose 文件固化下来等于给这套部署写了一份可读的说明书。services: zerotier: image: zerotier/zerotier:latest container_name: zerotier restart: unless-stopped network_mode: host cap_add: - NET_ADMIN - SYS_ADMIN devices: - /dev/net/tun volumes: - /opt/zerotier/data:/var/lib/zerotier-one security_opt: - no-new-privileges:truerestart: unless-stopped这个策略值得说一下。它和always的区别在于always是无论你怎么停都会重启包括你手工docker stop之后重启 Docker 服务unless-stopped会记住是你主动停的Docker 重启时不会把它拉起来。日常维护我倾向后者避免我在排查问题时它自己突然又起来干扰。security_opt: no-new-privileges配合前面的能力配置使用。意思是容器内的进程不能通过 setuid 之类的方式提权。虽然给了SYS_ADMIN但至少堵住了一条额外的提权路径。启动docker compose up -d docker compose logs -f日志里能看到节点地址和加入的网络。compose 文件建议放在一个专门的目录和挂载的数据目录同级方便整个目录打包备份tar czf zt-backup-$(date %Y%m%d).tar.gz /opt/zerotier备份出来的东西包含身份密钥属于敏感文件。我一般会再套一层加密扔到离线介质里不放在随便能访问的地方。4. 踩坑实录常见故障怎么查4.1 容器起来几秒就退出这是最高频的问题docker ps看不到容器docker ps -a显示 Exited。第一件事永远是看日志docker logs zerotier按我遇到的频次从高到低排第一种日志里出现cannot open /dev/net/tun之类的字样。原因就是宿主机没有 TUN 设备节点或者节点存在但权限不对。按 2.1 节的方法补建注意chmod 666别漏容器里的进程未必是 root。第二种日志里提示权限不足、创建接口失败。这是NET_ADMIN没给或者没生效。检查docker inspect zerotier | grep -A 5 CapAdd确认能力在里面。还有一种可能是宿主机的内核限制了容器的能力容器优化型系统上比较常见。第三种容器正常启动但立刻退出日志里什么都没有。这种往往是镜像的入口脚本判断某个环境变量缺失后主动退出。换成前台模式-it跑一次往往能看到更完整的输出。我第一次遇到时折腾了半天后来发现是没挂载数据卷脚本检测到目录不可写就退了。4.2 显示 OK 但两台机器互相 ping 不通这个问题比第一个更烦因为一切看起来都正常。排查要有顺序别乱试。第一步两边都执行listnetworks确认状态是OK且分配地址不为空。有一边是空的说明授权没生效回后台看是不是漏勾了或者勾错了设备。第二步确认两边的虚拟地址在同一网段且没有重复。地址重复这种事在小规模环境里反而更容易发生因为手工指定时容易手滑。ip addr在容器里看一眼就知道。第三步查防火墙。宿主机的防火墙如果是默认拒绝策略会把虚拟网卡的入站流量挡掉。临时验证可以先把防火墙放开测一下通了再针对性加规则。我给的建议是新建一条允许规则源地址限定为虚拟网段不要图省事直接全放。第四步查端口。host 模式下 ZeroTier 用 UDP 9993 与对端通信如果这个端口被占节点可能显示在线但实际上连不上对端只能靠中转。检查方法前面给过。端口被占时的一个典型表现是zerotier-cli peers里所有对端都显示RELAY没有DIRECT。走中转虽然也能通但延迟会高很多而且流量都从中间节点过。第五步看对端关系docker exec zerotier zerotier-cli peers这个命令列出所有已知对端重点看PATH这一列。DIRECT表示点对点直连RELAY表示走了中转。全是 RELAY 且延迟很高多半是网络环境对 UDP 不友好比如某些严格的网络策略这种情况只能接受中转或者换网络环境。注意这一步别太纠结能通就行直连是优化项不是必须项。4.3 小包通大包不通的怪现象症状ping通、ssh能连上打字正常、但scp传大文件卡死或断流、浏览器打开管理页面转圈。这几乎百分百是 MTU 问题。验证方法很直接ping -c 3 -s 1400 -M do 对端虚拟IP-M do是禁止分片-s 1400是指定数据部分大小。如果这个命令失败而-s 800能通基本可以确定是链路上某处的 MTU 小于你的设置大包被丢了。处理办法前面提过把虚拟网卡 MTU 降到 1400 或 1380。改完再测一般能解决。如果降到 1300 还有问题那可能就是上游网络的问题不是你能调的了。有一个细节容易忽略MTU 要在两端都调只调一端可能只解决单向传输问题。我遇到过上传正常下载卡住的情况查了半天发现是只有一端改了。4.4 重启之后节点身份变了这个坑最隐蔽。症状是机器重启后后台成员列表里多了一个新节点旧节点显示离线虚拟 IP 也变了之前配的路由全部失效。原因是没有持久化数据目录。ZeroTier 的身份标识存在/var/lib/zerotier-one/identity.secret和identity.public两个文件里这两个文件决定了你是谁。容器如果不挂载数据目录每次重建容器都是一套全新的身份后台自然就把你当成新设备了。还有一种变体挂载了目录但挂载路径写错了。比如挂到/var/lib/zerotier少了个-one而不是/var/lib/zerotier-one。容器跑起来不报错但身份文件写在容器内部容器一删就没了。这个错误我犯过一次排查时对着docker inspect看了好久才发现路径对不上。验证方法是容器启动后执行docker exec zerotier zerotier-cli info记下返回的节点地址重建容器后再看一次地址一致就说明持久化生效了。这个小检查值得养成习惯尤其是在调整挂载配置之后。5. 进阶几种落地场景和长期运维经验5.1 家庭自建服务的远程访问这是最常见的用途也是我这套方案一开始的目标。场景是这样的家里一台小主机跑着一堆自建服务有文件共享、有监控后台、有代码仓库都在192.168.50.10这台机器上。出门在外想访问用公司网络或者手机热点不可能去改路由器端口映射。做法是家里那台跑 ZeroTier 的机器作为网关节点虚拟地址固定10.147.17.1配好 NAT 和托管路由。然后在笔记本上装客户端加入同一个网络拿到10.147.17.10。这样笔记本在任何网络环境下直接访问192.168.50.10就能到家。有几个实践细节值得说。第一家里的网关节点最好选一台常年开机、功耗低的设备7x24 小时跑着。用主力台式机是不合适的关机了就断。我一开始用的是旧笔记本后来换成了一台小主机功耗从 60W 降到 10W 左右一年下来电费差不少。第二给自建服务加一层访问控制。组网通了不等于安全了虚拟网段里的任何设备都能访问你的服务。所以服务本身该有的密码、权限、审计一个都不能少别因为只有自己能进就裸奔。我的做法是在网关节点上再做一层限制只允许特定虚拟 IP 访问特定端口其他一律拒绝。第三手机端的体验。手机加入网络之后建议开按需连接不同系统里叫法不一样只在需要时建立连接而不是常驻。常驻会持续耗电我实测下来一天能多耗 5% 到 8%对续航敏感的话要留意。5.2 多地点设备互联第二个场景是把两个不同的物理局域网打通比如家里的网段和另一个办公地点的网段让两边的设备互相访问不用搬文件也不用跳板机。做法是两边各部署一个网关节点分别配好各自的 NAT 和托管路由然后在网络配置里把两条路由都加上。这样任意一端的设备访问对方网段时流量会自动走到对应的网关节点。这里有个容易踩的坑两个物理网段的地址段不能重叠。如果两边都是192.168.1.0/24这是很多路由器的默认段路由就彻底乱套了。协议栈会认为目标地址在本机直连网段内压根不会走虚拟网卡表现为怎么都通不了。检查方法很简单ip route一看便知。重叠了就得改其中一端的网段这是必须做的前置工作绕不过去。另一个经验是路由的优先级。主机上可能同时存在多条路由比如直连网段、默认网关、虚拟路由。如果虚拟路由的优先级metric设置不当可能被其他规则盖掉。加托管路由的时候可以指定 metric值越小优先级越高。我一般设成 100 左右让它比默认路由优先但不至于压过直连网段。5.3 安全加固与日常巡检组网工具本身是个入口配得随意就等于给自己开后门。这部分我踩过坑所以格外注意。关掉自动授权。组网工具默认可能开着新成员自动加入方便但危险。任何拿到网络 ID 的人都能进来。关掉之后每台新设备都要你手工点一下麻烦一点但心里踏实。定期清理成员列表。时间长了会积累一堆已经不用了的设备换掉的手机、重装的系统、报废的机器。这些僵尸节点仍然持有网络访问权限。我给自己定了个规矩每个季度清一次把超过三个月没上线的一律移除。收敛网关节点上的转发规则。第 2.3 节给的 NAT 命令是放行整个虚拟网段。如果只有固定几台设备需要访问内网把源地址收敛到那几台的具体 IP 会更安全iptables -t nat -A POSTROUTING -s 10.147.17.10 -o eth0 -j MASQUERADE iptables -t nat -A POSTROUTING -s 10.147.17.11 -o eth0 -j MASQUERADE多写几行换来的是即使虚拟网段里混进一台不该有的设备它也访问不到内网。日志巡检。ZeroTier 的日志默认不写文件用docker logs看。可以配 Docker 的日志驱动限制大小避免日志把磁盘占满docker run ... --log-opt max-size10m --log-opt max-file3 ...这条我强烈建议加上。踩过一次坑日志文件涨到几十个 G把磁盘写满导致容器不断重启最后花了大半天才定位到是日志的问题。版本升级。容器升级很简单docker pull zerotier/zerotier:latest docker compose up -d升级前先备份数据目录。虽然大多数版本升级是无感的但身份文件一旦损坏你就得重新加入网络、重新授权、重新配路由比较折腾。备份几秒钟的事别省。我个人在实际操作中的体会是这类网络组件的部署难点从来不在把命令敲对而在把网络拓扑想清楚。地址规划、网关位置、路由指向这三件事在纸上画明白了真正敲命令也就十分钟。反过来边敲边试多半会在某次重启后发现所有配置都失效了然后从头再来一遍。所以如果你正准备动手我建议先拿张纸把你所有的网段、设备、地址列一遍确认没有重叠、没有冲突再开始跑容器。这一步花的二十分钟能省掉后面好几小时的排查。