你可能已经决定自己跑模型,但卡在第一步:镜像拉下来、命令敲进去,容器起了却连不上端口,或者接口返回一堆看不懂的报错,不知道是显存、参数还是权限的问题。这篇不解释 vLLM 原理,只按部署顺序给一份可执行的清单:起服务前确认什么、启动参数怎么给、接口怎么验、报错按什么顺序查。
自己用 Docker 起一个 vLLM 推理服务,难点不在原理,而在顺序。很多人是镜像拉下来、命令敲进去,容器看着起了,端口连不上,或者请求一打就报错,然后开始瞎猜是显存不够还是参数写错。这篇按部署时间线拆开:起容器前先确认什么、启动参数按什么顺序加、接口分几步验、报错按什么顺序查。
全程只讲可执行动作,不展开 vLLM 的调度原理。你要是第一次做这类部署,建议照着顺序做一遍,每步都有验证方式,别跳步。涉及具体型号、镜像标签和价格的地方,一律去站内页面核对当时的数字,这篇不写死。到 /models 可以先对一遍你手上模型的适配说明。
起容器前先把三件事定下来
容器是个黑盒,它只能看到你映射进去的东西。显卡、模型权重、端口这三样任何一样没映射对,后面所有调试都是白费功夫。先把这三件事确认完,再动手敲 docker run。
- 宿主机侧的显卡驱动和容器运行时先跑通:在宿主机上能正常识别显卡,才谈得上映射进容器;容器里不认卡,九成是宿主机这边就没准备好;
- 模型权重先定来源和挂载方式:本地目录挂进去还是容器内下载,两条路的排查方式完全不同;挂载路径写错、属主不对、只读挂载是启动失败的高频原因,挂载前先在宿主机上确认能读能写;
- 模型和框架版本先对齐:权重格式和镜像内版本不匹配会直接加载失败,选镜像前到 /models 对一遍该模型的适配说明;
- 端口、缓存目录、并发上限这三个要暴露的值提前想好,起完再改一次就得重启一次。
| 检查项 | 怎么验证 | 不对会怎样 |
|---|---|---|
| 宿主机显卡 | 宿主机上能识别到卡 | 容器内报找不到设备 |
| 权重挂载 | 宿主机路径可读写、属主正确 | 启动即失败或加载报权限错 |
| 版本适配 | 对照 /models 上的适配说明 | 权重加载失败或输出异常 |
| 端口占用 | 宿主机上端口没被别的进程占 | 容器起了但连不上 |
启动参数按这个顺序给
新手最容易犯的错,是把网上抄来的一长串优化参数一次全堆上去,结果跑不起来也不知道是哪一项的问题。正确做法是做加法:先最小可跑,再逐类往上加,每加一类验证一次。这个顺序本身就是排查顺序。
- 第一步:最小可跑参数只给模型路径、监听地址、服务端口这三项,目标是先把服务起来。能起说明镜像、权重、显卡映射都没问题;起不来问题就锁定在这三项里,不用怀疑参数。
- 第二步:显存相关项单卡放不下就减并行度或换量化权重。具体能塞多少,按模型的参数量和精度提前算一遍,或者先小后大试,不要凭感觉调。这一项决定的是能不能跑,不是跑多快。
- 第三步:并发与调度项最大并发、批处理大小、队列策略这几个一起调,它们决定吞吐和延迟的取舍。值给大了会 OOM,给小了请求排队严重。改完用下面的接口验证步骤压一下,看延迟随请求数的变化。
- 第四步:对外暴露项鉴权、请求限额、日志级别这些是上线前才需要收敛的,本地调通阶段可以先宽松,调通了再逐项收紧,避免调试时被鉴权挡住。
接口怎么验:从能通到能用
接口验证不是打一次通了就完事。要分四步,每一步失败指向的原因都不一样,顺着走能省掉大量瞎猜。下面用占位地址,实际端口换成你启动时定的那个。
# 第一步:只验证服务端口通不通
curl -sS http://127.0.0.1:<端口>/health
# 第二步:验证模型真在干活,发一个短提示词
curl -sS http://127.0.0.1:<端口>/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{"model":"<模型名>","messages":[{"role":"user","content":"你好"}]}'- 第一步不通
- 基本是端口映射错或容器没真正起来,回上一节查端口和容器状态
- 返回空或乱码
- 通常是权重没加载对或版本不匹配,回 /models 对适配说明
- 首次请求特别慢
- 正常的加载开销,后续请求恢复就没问题,一直慢才需要调参
- 并发一高就OOM
- 并发上限或批处理给大了,降下来再压
- 先测通不通:用一个最轻的健康检查请求打端口,失败就查映射,不要继续往下调模型参数;
- 再测模型是否真在干活:发一个短提示词,看返回内容是否合理;返回空、乱码或明显不相关内容,优先怀疑权重;
- 然后量延迟基线:分别记录首次请求和连续请求的耗时,首次慢是加载开销,区分开才不会被误判成性能问题;
- 最后按业务场景压并发:看延迟随请求数怎么变,这一步的结论才决定并发上限该设多少;
- 把每次验证的结论记一行,出问题时这份记录比重新猜一遍快得多。
起不来、连不上、跑着跑着挂:排查顺序
报错信息往往不直接指向根因,所以按「容器起不来 → 容器活着连不上 → 连上但请求报错 → 跑一段时间变慢」这个顺序排查,每一层只查几个固定点,不要跨层乱试。
| 现象 | 优先查 | 常见原因 |
|---|---|---|
| 容器起不来 | 日志最后几行 | 权重路径错、显卡没映射、镜像内依赖版本不匹配 |
| 容器活着但连不上 | 端口映射、监听地址、防火墙 | 监听只绑了容器内回环,或宿主机端口被占 |
| 连上但请求报错 | 显存与参数边界 | 显存不足或参数越界 |
| 跑一段后变慢或挂 | 显存碎片与缓存 | 重启能恢复基本是这个方向 |
- 容器起不来先看日志最后几行,别从头翻,三类高频原因基本都在末尾;
- 连不上按固定顺序查:端口映射、监听地址是不是只绑了容器内回环、宿主机防火墙;
- 请求报错先分显存不足还是参数越界,显存问题优先降并发或换更低精度权重,不要一上来就换卡;
- 跑一段时间后变慢,重启能恢复的话基本是显存碎片或缓存堆积,长期解法是限制并发加定期回收,而不是靠重启续命。
什么情况下别硬上这套方案
容器化部署有它的收益,也有它的代价。下面几种情况,硬上反而更费时间,提前判断能省掉一轮返工。
- 只是想在本机单人试一个模型:更轻量的本地推理工具通常比容器化服务省事,容器化的收益在于多实例和统一交付,单人不吃这个收益;
- 显卡规格或驱动受限、模型权重和现有镜像适配差得远:先评估换模型版本还是换部署方式,硬调参数往往耗掉的时间比换方案多;
- 没有持续在线的运维需求:按量调用接口的综合成本可能更低,自己起服务的价值主要在数据不出内网和可控性上;
- 团队没人长期维护这套服务:没人盯的推理服务,出问题时恢复时间会很长,这种场景不如把可用性交给外部。
容器化的收益在多实例和统一交付,不在「能不能跑起来」;如果你的场景不吃这个收益,选更轻的路子不丢人。下一步搭起来之前,先去模型库对一遍你手上模型的适配说明,再决定镜像和参数;想估一下自建和按量调用的成本差,到价格追踪页核对当时的数字,别凭印象拍。→
常见问题
容器里看不到显卡怎么办?
先确认宿主机驱动正常,再确认启动容器时确实把显卡设备映射进去了,容器只是继承宿主机的可见范围,宿主机看不到容器也看不到。还有一种情况是容器运行时本身没配好,换一个已知能跑通的方式重试一次来排除。具体版本要求到站内的部署测算页面核对。
服务起来了,接口请求一直超时是什么原因?
按顺序排:先看端口映射对不对,再确认监听地址不是只绑在容器内回环上,然后看请求是不是排在了长队列后面导致等待时间超过超时阈值。如果并发给得过高,显存吃紧也会表现为响应极慢而不是直接报错。
启动时显存不够,是换卡还是降配置?
先降配置:减少并发、调小批处理、换更低精度的权重,这三步通常能挤出不少余量。换卡成本高且要重新评估整机方案。能塞多少要按模型参数量、精度和并发一起算,别只看显存容量这一个数,站内有按模型算显存的页面可以对着算。