网络测速这件事,很多人第一反应是打开某个公共测速网站点一下了事。但如果你在运维内网、调试跨地域链路,或者需要给客户演示一条专线的真实带宽,公共测速站就不太够用了——节点不可控、结果受对端影响大、数据也不在自己手里。我这两年反复用到的一个方案,是用 Docker 把 LibreSpeed 跑起来,几分钟就能搭一套属于自己的测速服务,界面干净、结果可信、部署成本几乎为零。这篇就把我从零搭建到实际踩坑的完整过程摊开讲清楚,包括为什么选它、Docker 部署的每一步在干什么、参数怎么调、以及那些文档里不会写的坑。
LibreSpeed 本身是一套开源的网络测速工具,前端是纯静态页面,后端负责收发数据、计算延迟和抖动,整体非常轻量。它解决的问题很直接:给你一个可以自己掌控的测速端点,测的是"你的浏览器到这台服务器"之间的真实链路质量,而不是某个第三方节点的结果。适合的人群也挺广——运维和网络工程师拿它做内网带宽验证,开发者拿它做服务上线前的链路体检,普通爱好者想在家里 NAS 上挂一个自用测速页也完全没问题。下面我按实际动手的顺序往下走,每一步都会说清楚"为什么这么做"。
1. 为什么我最终选了 LibreSpeed 而不是别的测速方案
在动手之前,先把这个选型问题讲透,因为很多人一上来就照着教程敲命令,结果搭完发现方向就不对。测速工具大致分几类:一类是公共测速网站,点开即用但节点不受控;一类是商业测速服务,功能全但要付费且数据出境;还有一类就是 LibreSpeed 这种可自托管开源的方案。我三种都用过,最后长期留在工具箱里的是第三种,原因不是它功能最多,而是它在"可控性"和"轻量"之间找到了一个很舒服的平衡点。
1.1 自托管测速到底解决了什么痛点
公共测速站最大的问题是"你不知道对端是谁"。它可能给你分配了一个跨了好几个运营商、绕了半个国家的节点,测出来的数字跟你实际访问自己服务的体验完全对不上。而自托管之后,测速端点就是你自己那台机器,测出来的就是浏览器到这台机器的真实往返质量,这个数据才有决策价值。举个实际场景:客户抱怨访问你们服务慢,你在服务所在机房起一个 LibreSpeed,让客户打开测一下,如果数字很好,那问题大概率在客户本地网络;如果数字很差,那链路问题就实锤了。这种"甩锅有据"的能力,是公共测速站给不了的。
另一个痛点是数据隐私。有些内网环境根本不允许访问外部测速站,或者测速结果本身涉及链路拓扑信息不方便外传。自托管方案所有数据都在自己手里,测完即走,不留痕。这一点在给企业做交付时特别重要,客户看到你是本地部署的,信任度完全不一样。
1.2 LibreSpeed 的架构为什么适合容器化
LibreSpeed 的架构非常"容器友好"。它的前端是一堆静态文件(HTML/CSS/JS),后端是一个用 PHP 或 Go 写的小服务,负责生成测试用的数据块、接收上传、计算指标。整个东西没有数据库依赖,没有复杂的状态管理,配置基本靠几个环境变量和配置文件搞定。这意味着它天然适合塞进一个容器里跑,镜像小、启动快、迁移方便。
我用的是社区维护的linuxserver/librespeed镜像,这个镜像把 PHP 后端和前端静态资源都打包好了,还内置了可选的数据库支持(默认用 SQLite,也可以接 MySQL/PostgreSQL 存历史结果)。对于绝大多数自用场景,SQLite 就够了,连数据库容器都不用起,一个容器解决问题。这种"单容器可跑、按需扩展"的特性,正是我选它的核心理由——先用最简单的形态跑起来验证需求,需要存历史数据了再升级,不用一开始就搞一套复杂的编排。
1.3 和其他自托管方案的横向对比
市面上能自托管的测速方案不止一个,我简单列个对比,方便你判断自己该选哪个:
| 方案 | 部署复杂度 | 资源占用 | 结果可信度 | 适合场景 |
|---|---|---|---|---|
| LibreSpeed | 低(单容器) | 很低 | 高 | 内网验证、自用、快速演示 |
| 基于 iperf3 自建 | 中(需客户端配合) | 低 | 很高 | 纯带宽压测、专业链路测试 |
| 商业测速 SDK 自托管 | 中高 | 中 | 高 | 有品牌需求的产品集成 |
| 公共测速站 | 无 | 无 | 受对端影响大 | 随手一测 |
iperf3 的带宽测试其实更"硬核"、更精确,但它需要两端都装客户端、敲命令行,不适合让非技术人员打开浏览器就测。LibreSpeed 的价值就在于它把专业测速包装成了一个网页,任何人打开就能用,同时后端测的又是真实链路数据。所以我的结论是:要精确压测用 iperf3,要"给人用、能演示、能自证"用 LibreSpeed,两者不冲突,我通常是搭配着用。
2. 动手前的环境盘点与镜像选择
选型定了,接下来是动手。但我不建议你直接复制粘贴一堆命令就跑,先把环境盘一遍,能省掉后面一大半的排错时间。这一节讲清楚跑 LibreSpeed 需要什么、镜像怎么选、端口和目录怎么规划,这些前置决策做对了,后面基本一路顺。
2.1 宿主机需要满足的最低条件
LibreSpeed 对宿主机的要求低到几乎可以忽略。一台 1 核 1G 的云主机、一台闲置的树莓派、甚至家里 NAS 的 Docker 环境,都能跑得很稳。真正需要关注的不是 CPU 和内存,而是网络出口带宽和网卡性能——因为测速本身就是在压网络,如果你的宿主机网卡只有百兆,那测出来永远超不过百兆,这不是软件的问题。
我一般会先确认三件事:Docker 引擎版本(建议 20.10 以上,太老的版本对端口映射和网络模式支持有差异)、宿主机防火墙状态(后面要放行端口)、以及磁盘剩余空间(镜像加数据也就几百兆,但留点余量总没错)。用下面几条命令快速确认:
docker --version docker info | grep -i "server version" df -h /提示:如果宿主机本身跑在一台带宽很小的机器上,测速结果会被宿主机出口带宽"封顶"。想测真实链路,最好把 LibreSpeed 部署在离被测目标近、且出口带宽足够的位置。
2.2 linuxserver 镜像的标签怎么挑
linuxserver/librespeed这个镜像的标签策略比较清晰,常用的就几个:latest跟着最新稳定版走,latest之外还有带版本号的标签。我的习惯是生产环境用固定版本号标签,测试环境用 latest,这样避免某天自动拉取新版本后行为变化导致意外。拉镜像的命令很简单:
docker pull linuxserver/librespeed:latest拉完之后可以用docker images确认一下大小,通常在一百多兆的量级,非常轻。这里有个小细节:linuxserver 系列的镜像都遵循统一的 PUID/PGID 约定,用来控制容器内进程以什么用户身份读写挂载目录。如果你挂载了配置目录,记得把 PUID/PGID 设成宿主机上对应目录的属主,否则可能出现权限问题写不进去。这个坑我后面会专门讲。
2.3 端口、目录与网络模式的规划
端口规划上,LibreSpeed 容器内部监听的是 80 端口(HTTP)。映射到宿主机时,我一般选一个不冲突的高位端口,比如8080,避免和宿主机上已有的 Web 服务打架。如果你打算对外提供服务,前面通常还会挂一个反向代理做 HTTPS,那时候容器端口就映射到本地回环地址即可,由代理转发。
目录规划上,需要持久化的是配置和(可选的)数据库文件。linuxserver 镜像默认的配置路径是/config,我习惯在宿主机建一个明确的目录挂进去,比如/opt/librespeed/config。这样容器重建、升级都不会丢配置。网络模式用默认的 bridge 就行,除非你有特殊的内网直通需求才考虑 host 模式——host 模式虽然省掉一层 NAT、测速数字可能略高一点点,但端口管理会变乱,自用场景没必要。
3. 用 docker run 把服务先跑起来
环境盘完,先用最直接的docker run把服务跑起来验证一遍。这一步的目的不是最终部署,而是用最短路径确认"这套东西在我这台机器上能跑通"。跑通之后再考虑用 compose 固化配置,这个顺序很重要——先验证再固化,比一上来就写一堆编排文件然后对着报错抓瞎要高效得多。
3.1 一条命令启动与参数逐项拆解
启动命令大概长这样:
docker run -d \ --name librespeed \ --restart unless-stopped \ -p 8080:80 \ -e PUID=1000 \ -e PGID=1000 \ -e TZ=Asia/Shanghai \ -v /opt/librespeed/config:/config \ linuxserver/librespeed:latest我逐项说一下每个参数在干什么,因为很多人抄命令但不知道含义,出问题就懵。-d是后台运行;--name给容器起个固定名字方便后续操作;--restart unless-stopped保证宿主机重启或容器异常退出后能自动拉起,这个对长期跑的服务几乎是必加项;-p 8080:80把宿主机 8080 映射到容器 80;PUID/PGID控制文件权限身份;TZ设时区,影响日志时间戳;-v把配置目录持久化出来。
启动后立刻用docker ps看容器状态,再用docker logs librespeed看启动日志。正常情况下日志里会看到 Web 服务启动的信息。如果容器起来又立刻退出,八成是端口被占用或者挂载目录权限不对,日志里会有明确提示。
3.2 首次访问与界面初体验
容器跑起来后,浏览器打开http://宿主机IP:8080,应该能看到 LibreSpeed 的测速界面。界面很朴素:一个大的开始按钮,测完显示下载、上传、延迟、抖动几项指标,下面还有个结果分享的入口。第一次看到这个界面别嫌它简单,它的测速逻辑是实打实的——下载测试会从后端拉取多个数据块,上传测试会往后端推数据,延迟测试会发多次小请求算往返时间。
第一次测的时候建议多测两三次,取一个稳定值。因为首次测试可能受浏览器缓存、TCP 慢启动影响,数字会偏低。我实测下来,同一链路连续测三次,后两次的结果基本就稳定了,这个稳定值才是可信的。
3.3 验证测速结果是否可信的方法
怎么判断测出来的数字靠不靠谱?我有个简单的交叉验证法:在同一台宿主机上用iperf3或者直接curl下载一个大文件,看看实际吞吐和 LibreSpeed 报的下载速度是否在同一量级。如果差距巨大,那要么是测速端点配置有问题,要么是中间有代理或限速。正常情况下两者应该比较接近,LibreSpeed 因为走的是 HTTP 多连接,数字通常会略高于单连接 curl。
还有一个验证点:延迟指标。如果你测的是同机房或同内网的机器,延迟应该在个位数毫秒甚至更低;如果测出来几十上百毫秒,那要么链路确实绕了,要么测速端点根本不在你以为的位置。这个交叉验证能帮你快速判断"数字是不是真的"。
4. 用 compose 固化配置并做进阶调优
docker run验证通过后,我强烈建议转成docker-compose.yml管理。原因很实在:命令参数记不住、迁移时容易漏参数、升级时想改配置还得重新拼命令。compose 把这些都写进文件,版本可控、迁移就是拷一个文件的事。这一节把 compose 配置写清楚,再讲几个真正影响使用体验的调优点。
4.1 compose 文件的结构与关键字段
对应的 compose 文件大概是这样:
services: librespeed: image: linuxserver/librespeed:latest container_name: librespeed restart: unless-stopped ports: - "8080:80" environment: - PUID=1000 - PGID=1000 - TZ=Asia/Shanghai - PASSWORD_FILE=/config/htpasswd volumes: - ./config:/config healthcheck: test: ["CMD", "curl", "-f", "http://localhost/"] interval: 30s timeout: 5s retries: 3这里我加了两个docker run版本没提的东西:PASSWORD_FILE和healthcheck。前者用于给测速页加一个简单的访问密码(后面细说),后者让 Docker 定期探活,配合编排工具能自动重启不健康的容器。healthcheck里用curl探本地 80 端口,注意容器内不一定装了 curl,如果探活一直失败,可以换成wget或者干脆去掉,别让它误判。
启动用docker compose up -d,停止用docker compose down,升级镜像用docker compose pull && docker compose up -d。这套流程跑顺了,日常维护基本就是这三条命令。
4.2 给测速页加访问密码的正确姿势
LibreSpeed 支持一个轻量的密码保护,适合不想让测速页完全公开的场景。它的机制是读取一个 htpasswd 格式的文件,里面存用户名和密码哈希。生成这个文件可以用htpasswd命令(Apache 工具包里的),也可以用在线工具生成后手动写入。生成后把文件放到挂载的 config 目录下,再通过PASSWORD_FILE环境变量指向它。
这里有个坑要提醒:htpasswd 文件的路径是容器内路径,不是宿主机路径。你挂载的是./config:/config,那文件在宿主机是./config/htpasswd,在容器里就是/config/htpasswd,环境变量要写容器内路径。我第一次配的时候写了宿主机路径,结果密码一直不生效,排查了半天才发现是路径搞错了。另外密码保护只是"防君子不防小人"的轻量措施,真要严格鉴权还是得靠反向代理层的认证。
4.3 结果存储:SQLite 够不够用,什么时候该上 MySQL
默认情况下 LibreSpeed 不存历史结果,测完就没了。如果你想保留测速记录(比如做链路质量的长期监控),可以开启数据库存储。镜像内置支持 SQLite、MySQL、PostgreSQL 三种。我的建议很明确:个人自用和小团队,SQLite 完全够用,它零配置、单文件、备份就是拷一个文件,没有任何运维负担。
什么时候该上 MySQL?当你需要多实例共享结果、或者要做复杂的查询统计、或者结果量特别大(比如每天成千上万次测速)的时候。对绝大多数场景,SQLite 的性能绰绰有余。开启 SQLite 存储需要在配置里指定数据库类型和路径,具体字段参考镜像文档,核心就是把DB_TYPE设成sqlite,路径指向/config下的一个文件。配好之后测几次,去 config 目录看有没有生成.db文件,有就说明生效了。
5. 反向代理、HTTPS 与对外暴露的注意事项
服务在内网跑通之后,很多人会想把它暴露到公网,方便随时随地测。这一步有几个必须想清楚的问题:要不要 HTTPS、反向代理怎么配、以及暴露出去之后的安全边界在哪。这一节讲清楚这些,避免你搭好了却因为配置不当出问题。
5.1 反向代理转发的关键配置点
用 Nginx 或 Caddy 做反向代理是最常见的做法。核心配置就是把外部域名的请求转发到宿主机的 8080 端口。以 Nginx 为例,一个最小可用的 location 块大概是这样:
location / { proxy_pass http://127.0.0.1:8080; 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_read_timeout 300s; proxy_send_timeout 300s; client_max_body_size 100m; }这里几个参数值得单独说。proxy_read_timeout和proxy_send_timeout要调大,因为上传测速会持续推数据好几十秒,默认的 60 秒可能不够,超时了测速就中断。client_max_body_size也要放大,否则上传测试的数据块会被代理直接拒掉。这两个是我踩过的实打实的坑——一开始测上传总是失败,查了半天才发现是代理的 body size 限制。
5.2 HTTPS 之后测速数字为什么会变
上了 HTTPS 之后,你可能会发现测速数字比 HTTP 时略低,这是正常的。TLS 握手和加解密本身有开销,尤其在小数据块和高并发连接下,CPU 加解密会成为瓶颈。如果你的宿主机 CPU 比较弱,这个差异会更明显。所以做链路基准测试时,我一般用 HTTP 直连测"纯链路能力",用 HTTPS 测"真实用户体验",两个数字都有意义,别混为一谈。
另外提醒一点:如果反向代理和 LibreSpeed 不在同一台机器,代理到容器的这一段也会消耗带宽,测出来的数字反映的是"浏览器到代理"这一段,而不是"浏览器到测速容器"这一段。要测后者,就得让代理和容器在同一台机器上,或者干脆直连容器端口。
5.3 公网暴露的安全边界
把测速页暴露到公网,本质上是开放了一个会消耗带宽的端点。有几点必须注意:一是加访问密码或限制来源 IP,避免被当成免费带宽被人刷;二是注意流量成本,测速本身很吃流量,公网按流量计费的机器要算好账;三是别把管理接口一起暴露出去。我见过有人图省事把整个容器所有端口都映射出去,结果配置目录也能被访问,这就很危险了。
注意:测速端点被滥用会直接消耗你的出口带宽和流量费用。公网部署务必配合访问控制,并定期看流量账单。
6. 实测中踩过的坑与排查链路
前面讲的多是"应该怎么做",这一节讲"做的时候哪里会翻车"。这些都是我在不同环境里真实遇到过的,每个坑我都把排查过程写出来,你可以照着这个思路复现定位,而不是只记一个结论。
6.1 容器起来了但页面打不开
这是最高频的问题。排查顺序我固定为四步:先docker ps看容器是不是真的在 running 状态(有时候是 restarting 循环);再docker logs看有没有报错;然后宿主机上curl http://127.0.0.1:8080看本地通不通;最后从另一台机器访问看是不是防火墙问题。这四步能把问题范围从"容器内"一路缩到"网络层"。
我遇到过一次容器 running、日志也正常、本地 curl 通,但外部访问不了,最后发现是宿主机防火墙没放行 8080。还有一次是端口映射写成了8080:8080,但容器内实际监听的是 80,映射错了端口,页面自然打不开。这类问题看着玄乎,按上面四步走基本都能定位。
6.2 上传测速总是失败或数值异常低
上传测速失败,九成是中间环节限制了请求体大小或超时。如果你前面挂了反向代理,先查client_max_body_size和超时设置;如果是直连容器还失败,检查宿主机有没有其他中间层(比如某些安全网关)在拦截大请求。数值异常低则可能是宿主机上行带宽本身就小,或者测速时后台有其他大流量任务在抢带宽。
我有个习惯:测速前先docker stats看一眼容器资源占用,再在宿主机上iftop或nload看一眼实时流量,确认没有别的进程在跑大流量。有一次测出来上传只有几兆,查了半天发现是宿主机上有个备份任务正在同步,把上行占满了。这种"环境干扰"是最容易被忽略的。
6.3 挂载目录权限导致配置写不进去
这个坑的典型表现是:容器能跑,但配置改了不生效,或者数据库文件生成不了。根因是容器内进程以 PUID/PGID 指定的身份运行,如果这个身份对挂载目录没有写权限,就写不进去。排查方法很直接:ls -ln /opt/librespeed/config看目录属主和权限,再对照 PUID/PGID 的值。不一致就chown一下宿主机目录,或者把 PUID/PGID 改成目录属主的值。
我一般建目录时就顺手把属主设好,避免后面来回折腾。这个细节在 linuxserver 系列镜像里是通用规律,不只是 LibreSpeed,其他同系列镜像也一样,记住这一点能省很多事。
6.4 测速数字忽高忽低的干扰因素
同一链路测速数字波动大,先别怀疑软件。常见干扰源有:Wi-Fi 信号不稳(无线测速天然波动大,能插网线就插网线)、宿主机上有其他容器在跑网络任务、测速时浏览器开了太多标签、以及测速端点所在机器的 CPU 被占满导致处理不过来。我排查这类问题的顺序是:换有线、关掉其他任务、多测几次取中位数。
还有一个容易被忽略的点:浏览器本身。不同浏览器、甚至同一浏览器的不同版本,测速结果都可能有差异,因为它们的并发连接策略和缓存行为不同。做对比测试时,尽量用同一个浏览器、清掉缓存再测,结果才有可比性。
7. 把它用起来:几个真实的使用场景
搭好只是开始,真正体现价值的是怎么用。这一节分享几个我实际用过的场景,给你一些启发,也顺便把前面讲的技术点串起来。
7.1 内网带宽验证与故障定位
这是最经典的用法。内网里两台机器之间传输慢,到底是网络问题还是磁盘问题?在目标机器上起一个 LibreSpeed,从另一台机器打开测一下:如果测速数字接近网卡理论上限,那网络没问题,慢在磁盘或应用层;如果数字远低于预期,那网络链路就有问题,再往下查交换机、网线、网卡协商速率。这个判断过程几分钟就能完成,比盲目抓包高效得多。
我印象很深的一次,某内网服务访问慢,大家一开始都怀疑是应用代码问题,结果用 LibreSpeed 一测,两台机器之间带宽只有理论值的十分之一,最后定位到是某段网线的协商速率掉到了百兆。这种问题不测网络根本发现不了。
7.2 服务上线前的链路体检
每次有新服务上线,尤其是跨地域部署的服务,我会在服务所在机房起一个测速端点,从几个典型用户所在区域各测一次,记录下基线数字。这样服务上线后如果用户反馈慢,就有对比依据——是链路本身就这样,还是上线后出了新问题。这个基线数据花不了多少时间,但排查问题时价值巨大。
做基线时我建议记录:测试时间、源 IP 段、下载/上传/延迟/抖动四项指标。存到 SQLite 里,时间长了就是一条链路质量曲线,能看出规律性的波动(比如某些时段带宽被占满)。
7.3 家庭网络与自建服务的日常体检
家里有 NAS 或者自建服务的人,挂一个 LibreSpeed 在 NAS 上很实用。手机连 Wi-Fi 测一下,就知道当前无线环境能跑多少;换个房间再测,就知道信号覆盖的死角在哪。我家里就是靠这个把路由器的摆放位置调了两次,客厅的无线速率提升明显。这种用法不需要多专业,打开网页点一下就行,门槛极低。
8. 长期维护:升级、备份与监控
服务跑起来之后,长期维护的几件事得心里有数。这一节讲升级策略、备份要点和简单的监控思路,都是让这套东西"能一直用下去"的关键。
8.1 镜像升级的正确节奏
linuxserver 系列镜像更新比较频繁,但我不建议无脑追新。我的做法是:测试环境跟 latest,生产环境固定版本号,每次升级前先看镜像的更新说明,确认没有破坏性变更再升。升级命令就是docker compose pull加docker compose up -d,compose 会自动用新镜像重建容器,配置因为挂载在宿主机所以不受影响。
升级后一定要回归测一次,确认页面能打开、测速正常、密码保护还在。我遇到过一次升级后配置字段名变了导致密码失效,虽然不影响测速,但暴露出去就不合适了。所以升级后的回归测试不能省。
8.2 配置与数据的备份要点
需要备份的东西其实就两样:挂载出来的 config 目录(里面有配置和可能的 SQLite 数据库),以及你的 compose 文件。备份方式随意,tar打包拷走就行。我一般写个小脚本定期打包 config 目录,保留最近几份,成本几乎为零。
tar -czf /backup/librespeed-$(date +%F).tar.gz -C /opt/librespeed config恢复的时候反过来,把 config 目录放回原位,compose 文件放回原位,docker compose up -d就恢复了。因为整个服务是无状态的(状态都在 config 里),迁移和恢复都特别简单,这也是容器化部署的一大好处。
8.3 用健康检查做轻量监控
前面 compose 里配的 healthcheck 就是最轻量的监控。容器不健康时docker ps会显示 unhealthy 状态,配合一些简单的脚本或告警工具就能做到"服务挂了能知道"。如果想更进一步,可以定期用脚本请求测速页并检查返回码,把结果记到日志里,出问题时有据可查。
我个人觉得对自用场景,healthcheck 加偶尔手动看一眼就够了,没必要上重型监控系统。工具是为需求服务的,过度工程化反而增加维护负担。
最后分享一个我自己的使用习惯:我会在测速页的书签里存好内网和公网两个入口,遇到"网络慢"的反馈时,第一反应不是猜,而是先打开测速页测一下,用数字说话。这个习惯帮我省掉了无数次无谓的争论——很多时候问题根本不在你以为的地方,而一个可信的测速数字,往往就是最快的那把钥匙。