docker 部署 vllm 大模型

模型与算力

讲清用 Docker 容器跑 vLLM 推理服务的完整流程:镜像与权重怎么挂、启动参数怎么给、显存与并发怎么估、起不来时按什么顺序排查。

本地或内网要把开源模型跑成 OpenAI 兼容接口,很多人第一反应是 vLLM,但真上手常卡在几处:镜像和权重怎么挂进容器、模型文件放本机还是先下进卷、启动参数里显存占用比和最大长度怎么填、卡在昇腾这类国产算力上又要换哪套镜像。这篇按「准备—起服务—验证—排错」的顺序,把容器化部署这条链路拆成可照做的步骤,并标出哪些判断要按你自己的卡和模型现算。

想给内网或者本地配一个 OpenAI 兼容的推理接口,vLLM 是很多团队的第一选择。但真到动手的时候,卡人的地方往往不是框架本身,而是容器这一层:镜像和权重怎么挂进去、模型文件放本机还是先下进卷、启动参数里显存占用比和最大长度怎么填、换到昇腾这类国产算力上又要换成哪套镜像。这几步每一步都有坑。

这篇按「准备—起服务—验证—排错」的顺序把链路拆开,每一步给判断标准和具体动作。需要提醒的是:显存怎么估、并发能开多少,跟你的卡型号、模型大小、序列长度强相关,本文不写死数字,凡是涉及具体数值的地方,都请你到站内对应的测算页面按自己的环境算。

起容器前先把四件事定下来

  • 确认卡的驱动与容器运行时:NVIDIA 路线要装好容器工具包并让容器能看见卡,昇腾路线要装对应的 NPU 驱动与容器插件,先跑一条列出设备的命令确认卡真被容器识别到,再谈起服务
  • 确认模型权重的落盘位置:是先在宿主机下好再用只读挂载挂进容器,还是让容器启动时在线拉。内网环境一律提前下好,别把下载时间算进启动时间
  • 确认镜像版本与权重格式是否对得上,不同分支对权重加载的支持范围不一样,具体哪些模型能跑哪个分支,到 /models/deploy 按你的模型查一遍再决定
  • 确认你要的接口形态:只做 HTTP 推理服务,还是同时要 OpenAI 兼容端点被上层应用调用,这会影响启动命令里要不要带对应的接口开关

这四件事里最容易跳过的是第二件。很多人习惯让容器启动命令里直接带模型仓库地址,在外网测试没问题,一到内网就卡住,然后花半天查网络,其实权重根本没下下来。先把文件落到宿主机固定目录,后面所有操作都基于这个目录,出问题也容易定位。

容器运行时
让容器能直接看到宿主机的卡,NVIDIA 和昇腾各有对应的工具包和插件,装之前先确认系统版本匹配
权重挂载
把宿主机上已下好的模型目录以只读方式挂进容器,容器内路径写启动命令时要引用同一个
接口开关
启动命令里控制是否暴露 OpenAI 兼容端点的参数,上层应用要对接就必须打开

启动命令与参数怎么给:一份可直接改的骨架

把启动命令拆成四段看:镜像与挂载、模型路径与名称、并行与显存相关参数、端口与接口开关。按段改,比整条抄一条长命令好排错。下面是一个骨架,实际用的时候把尖括号占位换成你自己的值。

docker run -d --name vllm-serve \
  --gpus all \
  -v /your/models:/models:ro \
  -p <对外端口>:8000 \
  <镜像名> \
  --model /models/<模型目录> \
  --served-model-name <对外模型名> \
  --tensor-parallel-size <卡数> \
  --gpu-memory-utilization <占用比> \
  --max-model-len <最大长度>
  • 常见必调项是显存占用比例和单次最大序列长度。前者给太小浪费卡、给太大会 OOM;后者直接吃 KV 缓存。这两个值怎么按模型和卡算,走 /models/deploy 里的部署测算页,别凭感觉填
  • 多卡场景要显式声明张量并行度,并且让它和你实际分配给容器的卡数一致,否则会出现只见一张卡在跑的情况。多机多卡还要额外处理通信网卡与主节点地址
  • 把命令写进 compose 或启动脚本而不是手敲:加了 restart 策略、把权重目录固定、把日志重定向到文件,之后排错靠日志而不是靠回忆
  • 宿主机上先把权重目录的权限确认一遍,容器内进程对只读挂载通常不需要写权限,但目录本身要能被读取,否则会报文件不存在或者权限拒绝

起来之后怎么验证:三层检查别跳

容器没退出不代表服务就绪,加载权重阶段通常最慢。验证要按三层走,每层确认过再进下一层,别跳步。

  1. 看进程与日志先确认容器在运行,然后进日志找模型加载完成的那一行。加载权重期间接口是不可用的,这时候打请求会失败,属于正常现象。
  2. 发一条最短请求用一条最简单的对话请求打一遍接口,确认返回格式、字段名、结束标记都符合预期。别等接了上层应用才发现返回结构不对。
  3. 逐步加并发压一下慢慢提高并发数,同时盯显存和生成速度。什么时候开始排队、显存什么时候顶到上限,这才是你后面配限流和超时的依据。

测速基线这块,如果你们团队内部对速度的口径不统一,可以先在 /tools/speed-test 上把外部链路的口径对齐,再回来讨论容器内部的实际表现,避免两边测的不是一回事。接口跑通后,如果要给上层应用或知识库工具用,地址和鉴权方式按那些工具的要求配,容器这边只要保证对外端口和鉴权开关一致。

起不来时的排查顺序

报错一大片的时候最忌逐个改参数试运气。按下面的顺序走,先分类,再定位,最后才动参数。

现象先查什么再查什么
容器直接退出镜像是否拉完整、启动命令有没有语法错误挂载路径是否存在、端口是否被占用
容器在跑但接口不通日志里模型加载是否完成对外端口映射、鉴权开关是否打开
报权重相关错误挂载进容器的路径下文件是否完整权重格式与镜像分支是否兼容
报显存不足先把显存占用比降下来再降单次最大长度和并发,逐步往回试
  • 先分「容器级」还是「推理级」:容器起不来查运行时、挂载路径权限、端口占用;容器起来了但服务报错,直接进日志找第一处报错,不要被后面几十行连锁报错带跑
  • 权重类报错优先怀疑三件事:挂载路径进容器后是否真的存在、文件是否完整、权重格式与当前镜像分支是否兼容。国产卡路线还要确认用的是对应分支的镜像而不是通用版
  • 显存类报错按「先降后调」处理:先降显存占用比例、降单次最大长度、降并发,确认能起来后再往上试,直到接近上限
  • 遇到确定不了的报错,别在原地改参数试运气,先把完整日志留下来,再对照站内已有的报错排查和框架对比类文章判断是路线选错了还是配置写错了
能起来和跑得稳是两件事。先把服务拉起来,再按并发和显存数据一点点把参数调到合适的位置,比一上来就追求最优配置靠谱得多。

昇腾路线要额外注意什么

如果你的卡是昇腾,前面通用 GPU 那套命令能参考但镜像必须换。昇腾走的是单独的适配分支,直接拿通用 GPU 镜像去试基本起不来,而且环境的版本匹配比通用路线严格不少。

  • 镜像不是一个:昇腾走的是单独的适配分支,别拿通用 GPU 镜像去试,先确认拿到的是对应分支的镜像
  • 环境比通用路线敏感:驱动、固件、容器插件三者版本要配套,升级其中任何一个都可能让原来能跑的组合起不来,变更前留好回退版本
  • 能力边界要提前查:多模态输入、多机多卡这些场景的支持程度和通用 GPU 路线并不一致,上线前按你的真实请求类型验证,别只验证纯文本对话就下结论
  • 具体支持到哪一档、哪些参数可用,以站内昇腾相关的部署文章和部署测算页当当时的记录为准,不要拿别处的结论套自己的环境

昇腾路线上线前建议多做一步:把你要用的全部请求类型都跑一遍验收,而不是只测一条纯文本对话就觉得没问题。边界能力的支持情况在不同分支之间会变,具体以站内相应部署文章和测算页当时记录的数字为准。

下一步镜像分支和参数的取值范围跟你的模型、卡、框架版本都相关,写死数字意义不大。部署前先把模型和卡的信息在测算页过一遍,拿到属于你自己环境的显存和并发基线,再回去改启动命令。

常见问题

容器里跑 vLLM,权重放宿主机挂进去好还是让容器自己下?

生产环境一律提前下好再只读挂载进容器。让容器启动时在线拉,会把下载时长算进每次重启,网络一抖就起不来,而且多副本会重复占带宽。挂载还有个好处:换镜像版本时权重不用动,回退只换镜像标签就行。

启动参数里显存占用比例给多少合适?

没有通用值。它取决于模型参数量、量化档位、你的卡显存和要留多少给 KV 缓存。先给一个偏保守的值把服务起起来,再用逐步加并发的方式往上试。具体按你的模型和卡算,去 /models/deploy 走一遍部署测算更靠谱。

昇腾卡上能不能直接用同一套 docker 命令?

不能照抄。昇腾要换成对应的适配分支镜像,并且宿主机侧要装匹配的驱动、固件和容器插件。参数名大体相似但支持范围不同,多模态和多机多卡尤其要单独验证。上线前按站内昇腾部署相关文章过一遍清单。

本文依据各平台公开文档与官方公告整理,只做中文归纳;具体做法、参数与限制以官方文档为准。