ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Docker部署Speedtest-X:自建内网测速服务与反代排坑指南

Docker部署Speedtest-X:自建内网测速服务与反代排坑指南 先泼个冷水很多人以为自己家里宽带慢其实是路由器到电脑这一段不行。公共测速网站只能告诉你“互联网出口”什么样测不出内网交换机、AP、NAS 之间的真实吞吐。我手上几台设备常年要验证链路状况最后干脆自己用 Docker 装了一个 Speedtest-X 测速服务浏览器打开就能测局域网内任何终端都能用不用装客户端也不用等公共节点响应。这篇文章就是把整个部署过程、参数选型和常见坑完整过一遍适合手里有 NAS、软路由或者云服务器的朋友照着做基本十分钟就能上线。1. 为什么自建测速服务而不是去用在线测速1.1 在线测速解决不了的几个场景公共测速平台适合测“我能不能跑满宽带”但它本质上是一条“终端到测速服务器之间的全链路测速”。你的数据经过了家猫、路由器、运营商接入、骨干网最后才到对方机房。任何一个环节抖动结果都会变差。问题在于当你把路由器换成新的 Wi-Fi 6 设备时你根本不知道瓶颈到底在内网还是出口。用在线测速测出来 700M你说不清是光猫不行、网线质量问题还是路由器转发能力不够。自建测速服务的最大价值就是把测速范围“切”到你想要的位置。比如把 Speedtest-X 放在家里 NAS 上手机连 Wi-Fi 测出来的就是手机到 NAS 这条内网链路的吞吐。再加上其他几台设备同时测基本能看出无线覆盖和漫游有没有问题。再比如在边缘机房部署一个实例就能快速验证多条运营商线路的实际可用带宽这比拿着 iperf3 在电脑前敲命令要直观得多。1.2 Speedtest-X 和其他测速方案怎么选先明确一点Speedtest-X 不是从零发明的测速协议它的核心玩法来自开源项目 LibreSpeed。LibreSpeed 原本是 PHP 后端Speedtest-X 用 Node.js 重新实现了服务端保留了浏览器端 JavaScript 生成流量、后端做往返统计的整套思路同时把部署方式简化到一条 Docker 命令就能跑。我用过好几类方案这里直接给个对比方案部署难度前端体验适合场景Speedtest-X极低Docker 一把梭接近 Speedtest 官方网页有进度、有曲线日常内网验证、给家人同事用LibreSpeed 原版需要 PHP 环境略繁琐界面朴素已有 PHP 环境不想引入 NodeOpenSpeedTestDocker 部署也简单现代化但配置项偏少快速演示、临时验证iperf3命令行需两端运行无 Web UI精确测 TCP/UDP 吞吐带参数控制Speedtest CLI单文件很快纯命令行脚本化定时测速、自动上报我的结论是自己日常用的时候如果只是想要一个“打开网页就能测、看着不丑、别人也能用”的服务Speedtest-X 是最省事的选择。如果你要做严谨的带宽审计那就不要依赖 Web 测速直接上 iperf3。两者不冲突Speedtest-X 可以作为常驻服务iperf3 作为临时仲裁工具。1.3 它的测速原理和流量模型Speedtest-X 的网页端会向服务端发起大量并发请求。下载测速时浏览器并行拉取后端生成的二进制数据块上传测速时浏览器把一段随机生成的数据通过 POST 请求不断推到服务端。延迟测试则是通过若干次轻量级的 HTTP 请求往返时间得出。这里需要理解一个关键点浏览器并发能力决定了测速结果的上限。浏览器对同一个域名的并发连接数是有上限的且 HTTP/1.1 和 HTTP/2 的行为还不一样。所以如果你通过 Nginx 做了反向代理一定要把不必要的缓冲关掉否则上传测速会非常诡异。后面我会专门写这一块。2. 部署前准备Docker 环境、镜像与端口规划2.1 Docker 环境要求和安装踩坑Speedtest-X 镜像是标准的 Linux 容器只要 Docker 能跑基本不需要额外依赖。但不同系统上 Docker 本身才是最大的坑。Linux 上最省心一条命令装好 Docker Engine 就能拉镜像。Ubuntu 下装完直接设开机自启sudo systemctl enable --now dockerWindows 上用 Docker Desktop 的时候最常见的问题是 Docker Desktop 启动失败报错提示虚拟化没有开启。这种情况根本原因多半是 BIOS 里 VT-x/AMD-V 没打开或者 WSL2 内核组件没装。先去“启用或关闭 Windows 功能”里确认勾选了“适用于 Linux 的 Windows 子系统”和“虚拟机平台”再退回 BIOS 看一眼虚拟化开关。这个问题我见过十几次基本都是这两处。NAS 设备上用群晖或威联通的话直接在套件中心装 Container Manager 或 Docker 套件就行。唯一要注意的是 NAS 的内存和空间虽然 Speedtest-X 很省但容器日志如果长年不清理会悄悄占掉好几个 G建议在日志驱动上做限制。2.2 镜像选择用哪个源、哪个标签Speedtest-X 的镜像发布在 GitHub Container Registry 和 Docker Hub 都有。国内服务器直接拉 GitHub 的镜像速度可能会让你怀疑人生建议先用 Docker Hub 的镜像名或者配置 Docker 的 registry mirror 加速。我用的是这样的命令拉取docker pull ghostchu/speedtest-x:latest如果你能从 GHCR 拉也可以用docker pull ghcr.io/ghostchu/speedtest-x:latest关于镜像标签我给你的建议是没有特殊洁癖就直接用 latest因为这类小项目更新不频繁latest 相对可靠。但如果你是一个有生产环境洁癖的人建议在写 compose 文件时固定到具体的版本号避免某天重启容器后自动升级到不兼容的配置格式。2.3 端口规划80、8080 还是自定义高位端口Speedtest-X 镜像内部默认监听 80 端口。最简单的做法是直接映射到宿主机 80docker run -d --name speedtest-x --restart unless-stopped -p 80:80 ghostchu/speedtest-x:latest但 80 端口太容易被其他 Web 服务占掉了。我自己习惯映射到 8080 或 3000 这种高位端口前面再挂一个 Nginx 做域名接入。端口本身不影响测速性能关键是你要记得把防火墙规则放行。如果映射高位端口比如-p 8080:80那么外部访问地址就是http://服务器IP:8080。凡是打不开的情形九成都是忘了放行防火墙端口剩下的是云服务商安全组没配。这里的坑在于很多人只关了本地防火墙忘了云控制台的安全组规则两头都要看别漏。2.4 资源占用预期一台多年旧电脑也能扛Speedtest-X 的容器资源占用非常低。单独跑一个实例内存占用大概在 80MB 到 150MB 之间波动空载时 CPU 接近 0。真正消耗资源的是测速那一刻因为要让数据流高速通过容器但如果你的测速目标本来就跑不满万兆这点压力不算什么。唯一需要留意的是磁盘。测速上传时数据要经过容器容器里的磁盘只发挥中转和缓冲作用。如果宿主机硬盘性能极差比如老式机械盘可能会出现上传测速结果虚低的情况。这时候建议把容器日志限制住或者直接部署在 SSD 磁盘上。不过说实话家用千兆环境下机械盘也能凑合跑影响有限。3. 快速部署与配置实操3.1 一条命令把服务跑起来先给直接能用的命令假设你要把服务暴露在宿主机 8080 端口docker run -d \ --name speedtest-x \ --restart unless-stopped \ -p 8080:80 \ ghostchu/speedtest-x:latest解释一下关键参数-d后台运行。--name容器名方便后续 stop/rm/logs 操作。--restart unless-stopped容器异常退出后自动重启除非你手动停止它。-p 8080:80宿主机 8080 映射到容器 80。跑完以后等两三秒直接看容器日志docker logs -f speedtest-x看到服务起来监听端口的日志就没问题。然后用浏览器访问http://你服务器IP:8080应该能看到一个类似 Speedtest 官方风格的页面中间有个大 GO 按钮。3.2 用 docker-compose 管理避免 Docker Run 命令遗忘单条命令虽然快但容器多了以后我强烈建议用 compose 文件把配置固化下来。创建一个docker-compose.ymlversion: 3.8 services: speedtest-x: image: ghostchu/speedtest-x:latest container_name: speedtest-x restart: unless-stopped ports: - 8080:80然后启动docker compose up -d将来更新版本也很简单docker compose pull docker compose up -d这里有个体会一定要养成交互式操作前先docker compose down、再修改配置、再up -d的习惯。直接改docker-compose.yml后用docker compose up -d虽然也能触发重建但很多人会在老的容器基础上把你搞糊涂最后容器没变新配置没生效。3.3 验证服务是否真的可用容器起来了不代表测速完全正常。浏览器打开页面后我建议做三件事第一点击页面上的测速按钮等一次完整下载和上传结束。第二看浏览器开发者工具的 Network 面板里有没有红字请求尤其是上传阶段。第三用手机开飞行模式后重新连同一个局域网 Wi-Fi再测一次排除电脑本身网络栈问题。如果你想在服务器本地快速确认接口状态可以这样curl -I http://127.0.0.1:8080如果返回 HTTP 200 或 302至少说明服务在响应。需要注意的是有些版本的页面根路径会 302 到带斜杠的地址这很正常。3.4 容器更新、备份与迁移Speedtest-X 的配置数据很少。官方镜像一般只提供运行时代码不涉及数据库文件。更新流程就是拉新镜像、删旧容器、用同样参数重新创建docker pull ghcr.io/ghostchu/speedtest-x:latest docker stop speedtest-x docker rm speedtest-x docker run -d --name speedtest-x --restart unless-stopped -p 8080:80 ghcr.io/ghostchu/speedtest-x:latest如果你跑的是官网默认版本迁移也只需要拷镜像或重新拉镜像没有数据迁移负担。这反而是它作为轻量工具的优势。4. 反向代理接入与安全加固4.1 为什么自建要加一层反向代理直接开 8080 端口访问当然能用但一旦你需要在多台设备、多个域名之间切换你会发现直接暴露端口有几个隐藏问题。一是没有 HTTPS浏览器可能被标记为不安全尤其在手机上访问时会被浏览器警告。二是端口的随机性导致别人记不住地址。三是你想限制某些人访问直接在 Speedtest-X 上用 IP 白名单做不太灵活。所以我建议在前面加一层 Nginx 或 Caddy。Nginx 做反代是很成熟的方案Caddy 则是自动 HTTPS 更省事。两者二选一我下面写 Nginx 的完整配置。4.2 Nginx 反代配置中容易忽略的参数这是我自己踩过多坑之后沉淀出来的最小可用配置server { listen 80; server_name speed.example.com; location / { proxy_pass http://127.0.0.1:8080; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_buffering off; proxy_request_buffering off; client_max_body_size 0; proxy_read_timeout 300s; proxy_send_timeout 300s; } }几个参数的作用逐个说清楚proxy_buffering off是下载测速的关键。如果不关Nginx 会先把上游的数据缓冲一段再转发给浏览器等于中间多了一次缓冲尤其是大文件传输时吞吐可能被压低表现就是下载速度始终上不去。proxy_request_buffering off和client_max_body_size 0是上传测速的关键。上传数据通过 Nginx 时默认 Nginx 会先 buffering 到磁盘如果你不关单线程并发上传的数据会被拖慢。client_max_body_size 0则是取消上传体积限制避免测速文件超过默认 1MB 被 Nginx 直接拦截。proxy_read_timeout和proxy_send_timeout是为了防止测速时间长导致连接被 Nginx 判定为超时断开。浏览器测一次 300 秒基本够用你可以根据自己的环境调。如果你用 Caddy配置会简单很多speed.example.com { reverse_proxy 127.0.0.1:8080 }Caddy 默认不会对上传请求做体积限制反向代理的缓冲也几乎没有干扰所以我很多内网机器用 Caddy 反而比 Nginx 稳。4.3 公网部署时的访问控制如果把测速服务放到公网我强烈建议至少做一层访问控制。最简单的是 Nginx Basic Auth# 生成密码文件 htpasswd -c /etc/nginx/.htpasswd speeduser然后在 server 块里加auth_basic Restricted; auth_basic_user_file /etc/nginx/.htpasswd;更高端一点可以用 IP 白名单allow 192.168.0.0/16; allow 10.0.0.0/8; deny all;聊一聊安全思路一个测速服务本质上就是让你上传下载数据它天然容易被耗流量。不加控制放在公网很可能被脚本拿来当免费流量池轻则多烧流量重则被恶意上传攻击打满带宽。至少加个 Basic Auth虽然不能防专业攻击但能挡掉 90% 的瞎扫。5. 常见问题与排查技巧实录5.1 容器启动失败与端口冲突症状是docker run后容器一直重启docker logs看到端口 bind 失败。原因基本都是宿主机端口被占用。先用一条命令查ss -lntp | grep 8080有进程占着就换端口或者杀掉占用进程。注意-p 8080:80里宿主机端口和容器端口都显示宿主机端口冲突才会报错。另一个基本功是容器状态确认docker ps -a docker inspect speedtest-x --format {{.State.Status}}如果是Restarting可以docker logs --tail 50看最后的报错。很多情况下不用猜日志已经告诉你了。5.2 测速结果明显偏低怎么定位瓶颈这是使用中最常见的抱怨明明跑到 500M 的宽带自建测速只有 200M。我归纳了四个排查方向第一看测速拓扑。如果 Speedtest-X 在 NAS 上而 NAS 再接路由器那么测速路径已经包含了 NAS 到路由器的物理链路。第二看服务器资源。测速那几秒用docker stats观察容器 CPU 和内存如果 CPU 跑到 100%说明容器所在宿主机性能不够或者并发请求太多。第三看攻击流是不是有 QoS 限制。某些路由器内置 QoS 会优先保障小包导致大流量吞吐被压低把 QoS 关掉再测。第四换 iperf3 做对比看是不是 Speedtest-X 本身的问题。我自己遇到过一个典型案例同一台 NAS 上跑 Speedtest-X用电脑 Wi-Fi 6 五米远测能跑 900M走到隔一间房的门边就掉到 300M。后来看 Wi-Fi 漫游和 AP 摆放位置才发现是信道干扰。这种时候 Speedtest-X 只是暴露了问题测速工具本身没有刁难你。5.3 反向代理后上传测速总是失败如果你没加反向代理时一切正常加了 Nginx 后测试到上传阶段就停住或失败九成是上传缓冲和体积限制的问题。检查以下几点确认client_max_body_size 0生效nginx -T | grep client_max_body_size确认proxy_request_buffering off生效nginx -T | grep proxy_request_buffering如果还是不行把proxy_read_timeout调到 600s 再试。注意 Nginx 版本太老对proxy_request_buffering的支持有限建议使用 1.7.11 及以上版本。5.4 内网环境测速误差的独家心得最后说一个关于数据解读的经验Speedtest-X 默认会显示下载、上传、延迟和抖动。很多人会盯着最高值但 Web 测速本质上是一锤子买卖受浏览器调度、系统缓存、后台下载影响巨大。我一般建议至少测三次取中位数并且测之前关掉所有大流量应用。同时内网测速时如果看到延迟极高比如几百毫秒先检查是不是无线链路有问题。有线连接下正常延迟应该在 1ms 到 5ms 以内。如果出现几十毫秒的抖动很可能是某个网卡驱动省电模式或者交换机端口协商异常。这比带宽本身更值得查。还有一个小技巧很多人的手机浏览器可能后台开了“省流量模式”这种模式会压缩大文件导致下载测速结果虚高。测速时最好关掉系统级省流量功能或者在电脑上用 Chrome 无痕窗口测排除扩展干扰。结尾我自己用 Speedtest-X 快一年了最大的感受是它把“内网测速”这个需求从命令行世界带到了普通浏览器里谁都能用。你不需要会背 iperf3 参数不需要装任何客户端手机上打开网页点一下就能知道链路是通还是堵。尤其是当你家里、公司里、机房里有多个网段要验证的时候一个轻量容器摆在固定位置随时测、随时有结果这种确定性比什么都重要。如果你已经有 NAS 或云服务器现在就拉一个镜像跑起来先用手机测一遍再用电脑测一遍。如果发现差距很大恭喜你这恰恰是自建测速服务存在的意义。只要你能忍受第一个晚上折腾端口和防火墙后面它就是一台永远不关机的“链路体检机”。
返回列表