你大概是在 GitHub 上翻到 vLLM 的官方镜像说明,复制了一条 docker run,结果容器起来了却拉不到模型,或者显存报错、端口连不上、客户端一直转圈。这篇不讲原理,只按顺序走一遍:确认环境、选镜像、挂模型、起服务、验证、排错,每一步都给出判断标准和失败时先查什么。
你在 GitHub 上翻到 vLLM 的官方镜像说明,照着复制了一条 docker run,结果容器是起来了,但模型拉不下来、显存报错、端口连不上、客户端转圈。这篇不讲原理,只按顺序走一遍:确认环境、选镜像、挂模型、起服务、验证、排错。每一步都给出判断标准和失败时先查什么。
整体思路是把链路拆成六段,每段都留一个能独立验证的检查点。前面一段没过就别急着看后面,不然日志里一堆报错你根本分不清哪个是根因。这也是一份能直接照着敲的操作顺序。
动手前先把三件事定下来
先别拉镜像。第一件事是确认宿主机能不能被容器看见显卡:驱动装好、容器运行时配好。这一步没过,后面所有报错都是白费力气。判断标准很直接——在容器里跑一个最小验证命令,能看到卡列表和设备信息才算过,看不到就先修运行时,不要一边报错一边怀疑镜像。
- 验证显卡可见性开一个最小的测试容器,让它在里面列出设备。能列出卡型号和数量就说明运行时通了;如果只看到空列表或直接报找不到设备,先回头配容器运行时。
- 确认模型来源想清楚模型是提前下到宿主机某个目录、再用挂载的方式给容器,还是让容器运行时自己去远端拉。前者一次下载多次复用,后者每次重来都要重下,网络和时间成本完全不同。
- 确认用法你是只想跑一次对话做个验证,还是要长期挂一个 OpenAI 兼容的服务端。这俩对启动参数和后续维护的要求不一样,先定下来再选镜像。
镜像怎么选:官方镜像的几种标签差别在哪
官方镜像一般按用途和版本分不同标签。选之前先想清楚:你是要「开箱能跑」,还是必须和现有环境里的某个版本对齐。前者挑官方说明里推荐的默认标签就行,后者就要去核对版本对应关系,别凭标签名字里的数字猜。
- 用途标签
- 面向「拿来就能跑」的场景,参数和依赖都配好了,适合第一次验证链路。
- 版本对齐标签
- 需要和你宿主机上的运行环境保持一致时用,具体对应关系去官方说明里核对。
- 标签拼写
- 拉取失败先检查 tag 是不是写错了、镜像名有没有多余空格,别急着换源。
- 拉取慢或超时,先判断是网络问题还是标签写错:换个明确的标签再试一次,还是慢就是网络。
- 换镜像之前先把 tag 拼写逐字核对一遍,大小写和短横线都要对。
- 如果团队里没人维护镜像版本,长期跑生产要想好更新和回滚流程,不然一次升级可能把服务搞停。
- 镜像体积和层数会影响首次启动时间,磁盘紧张时优先清掉旧的镜像层再拉新的。
把模型挂进容器:路径、权限和缓存目录
推荐把模型目录挂进容器,而不是在容器里重新下载。容器删了模型还在,重来一次不用重下。挂载前先确认宿主机目录的读权限和属主,容器里最常见的问题是「路径存在但读不了」,而且报错文案往往不直接指向权限,很容易被带偏。
| 检查项 | 判断标准 | 失败时先看什么 |
|---|---|---|
| 目录存在 | 宿主机上能 ls 出文件 | 路径拼写、挂载目标路径是否一致 |
| 读权限 | 容器内用户能读到文件 | 宿主机目录属主和权限位 |
| 权重完整 | 文件大小和目录结构符合预期 | 是不是下到一半断了 |
| 缓存空间 | 缓存目录所在分区有足够余量 | 镜像层、临时文件、权重是否挤在一个盘 |
给缓存目录单独留空间这点很容易被忽略。镜像层、临时文件和模型权重挤在一起,很容易撑满磁盘,表现出来的却是模型加载失败这种看起来跟磁盘无关的报错。所以磁盘余量要单独列一项检查。
起服务:常用参数按这个顺序调
先只把「模型路径 + 端口 + 服务端模式」三个参数给对,跑通再谈性能参数。一上来堆一堆参数,出问题最难定位是哪一条引起的。等服务确实起来了、能返回结果了,再逐步加并发、加上下文长度这些。
- 最小参数起服务只给模型路径、端口、服务端模式三个值,让服务先跑起来。这一步的目标是「进程活着」,不是性能。
- 显存参数保守起步显存相关参数从保守值开始试,根据实际显存余量逐步放开,别照着别人的配置直接抄,卡型不一样结果差很远。
- 再调上下文长度如果模型上下文长度超过默认值,需要显式调大,不然长输入会被截断或直接报错。具体取值到 /models/deploy 按你的模型和卡型算一遍。
验证服务真的通了:从容器内到容器外分三层查
服务进程活着不等于服务可用。分三层查:第一层在容器内部访问本机端口,能通说明服务活着;第二层在宿主机访问映射端口,能通说明端口映射没写错;第三层用外部客户端访问,能通才算对外可用。卡在哪一层,问题范围立刻缩小。
- 容器内访问:能通说明服务在监听;不通先看服务日志有没有正常启动。
- 宿主机访问映射端口:能通说明端口映射对;不通回头查启动命令里的端口映射。
- 外部客户端访问:能通才算对外可用;不通查防火墙和监听地址是不是只绑了本地。
- 用最小请求先验证接口,别一上来就丢长 prompt 和复杂参数,先确认返回格式对得上。
- 确认返回的是模型真实输出而不是空回或超时,输出速度可以到 /tools/speed-test 量一个基线,后面调参才有对照。
接口路径和请求体格式按 OpenAI 兼容方式组织。一份最小请求能通,再往上加东西;最小请求都不通,加再多参数也白搭。基线有了之后,你调任何参数都能和这个基线比,不然全凭感觉。
起不来时的排查顺序,别跳步
按「驱动 → 容器运行时 → 镜像拉取 → 模型加载 → 服务启动 → 端口对外」这个顺序查,前面没过就别看后面。很多人一上来就盯着模型加载报错,结果根因是运行时根本没配好。按顺序走,每一步都有明确的通过标准。
# 排查顺序示意,每一步过了再进下一步
# 1 驱动能否被容器看见
# 2 容器运行时是否配置正确
# 3 镜像能否正常拉取
# 4 模型能否加载进显存
# 5 服务进程是否监听端口
# 6 外部客户端能否访问| 症状 | 先查 | 再查 |
|---|---|---|
| 显存报错 | 批量大小和上下文长度是不是太大 | 量化方式是否和模型匹配,最后才考虑换卡 |
| 模型加载失败 | 权重文件是否完整、目录结构是否对 | 日志里具体断在哪一步 |
| 端口连不上 | 服务是否真的在监听 | 端口映射和监听地址有没有写对 |
| 客户端一直转圈 | 最小请求是否正常返回 | 响应体格式和超时设置 |
显存相关报错永远先降批量、降上下文,确认量化方式和模型匹配,再考虑换卡。换卡是最后手段,前面几步没试完就换卡,很可能换了还是同样的错,只是浪费了时间和资源。
什么情况下别用 Docker 这条路
Docker 不是所有场景都合适。如果你只是想在本机快速试一个模型,更轻量的本地工具会省很多事,可以对比 /local-llm-deploy-tools-compare 里的选项。容器方案的优势在于环境隔离和可复现,如果你的需求根本用不到这两点,那就是在给自己加负担。
- 只是本机快速试模型:轻量工具更快,不必搭容器。
- 需要多机多卡、跨节点调度:单容器方案要另做编排,先看清是不是已经超出 Docker 能覆盖的范围。
- 团队没人维护镜像版本:长期跑生产要考虑更新和回滚流程,不然一次升级就可能把服务搞停。
- 对启动时间极度敏感:容器冷启动有额外开销,热服务才划算。
常见问题
vLLM 官方镜像和社区镜像有什么区别,该用哪个?
官方镜像跟着上游版本走,更新及时但参数和依赖也更贴近上游默认值;社区镜像通常帮你配好了某些模型或环境,省事但版本可能落后。初次跑通建议用官方镜像,确认跑得动之后再按需要换。选之前先想清楚你是要跟上游版本,还是要省配置时间。
容器起来了但客户端连不上接口,先查什么?
按内到外三层查:先在容器内部访问端口,确认服务本身活着;再在宿主机访问映射端口,确认映射写对;最后用外部客户端访问。多数情况卡在第二步,端口映射漏写或者写成了只监听本机地址,服务端日志里通常能看出它实际监听在哪个地址上。
模型文件放在宿主机还是容器里下载?
放宿主机更稳。容器删了模型还在,换镜像重来时不用重下;而且下载走宿主机的网络,出问题也好排查。挂载时注意目录读权限,容器里报「找不到模型」很多时候其实是读不了那个目录,而不是文件真的不在。
显存报错是不是一定要换卡?
不一定。先看是加载阶段就爆还是推理阶段才爆:加载阶段爆往往是模型本身超出显存,需要考虑量化或换卡;推理阶段爆多半是并发和上下文太激进,把批量或上下文长度降下来通常能解决。具体能开到什么程度,可以到 /models/deploy 按模型和卡型估一遍再调。
能不能用同一套命令跑不同模型?
启动命令的骨架可以复用,但模型相关的参数要跟着改,尤其是上下文长度、张量并行数和量化方式。建议把每类模型的启动命令单独存一份,别用一个模板硬套,不然换模型时最容易出的就是参数不匹配导致的加载失败。