下面是我整理的一份 vLLM + OpenAI-兼容接口 在 Docker 上部署的较为详尽手册。可以根据你的环境(多 GPU / 单 GPU / CPU / 内存大小 / 模型大小 /安全 /网络部署方式等)做适当调整。
1. 背景与目标
- vLLM(“Very Large Language Model”)是一个高吞吐、内存效率较优的 LLM 推理与服务框架,支持批量调度、KV 缓存共享、模型量化等优化。(GitHub)
- 它提供一个 OpenAI API 兼容的服务端接口(支持
/v1/completions
,/v1/chat/completions
等)以替代 OpenAI 后端。(VLLM Docs) - vLLM 项目官方提供了一个 Docker 镜像
vllm/vllm-openai
,方便部署。(VLLM Docs)
我们的目标:在你的服务器/机器上,通过 Docker 方式部署 vLLM-OpenAI 服务,使得你可以通过标准 OpenAI API 接口调用本地模型。
2. 准备工作 / 先决条件
在开始之前,需要确认以下环境条件与准备:
项目 | 要求 / 建议 | 说明 / 建议值 |
---|---|---|
操作系统 | Linux(Ubuntu / CentOS / Debian 等) | Docker 在 Linux 上支持较好 (Windows 有兼容方案,但不是首选) |
GPU | 支持 CUDA 的 GPU 卡 | 推荐使用 NVIDIA GPU,如果要做大模型推理,多卡支持会更好 |
CUDA / 驱动 | 驱动 + CUDA Toolkit 安装、匹配 GPU | 保证宿主机能正常运行 GPU 加速推理 |
Docker & NVIDIA Container Toolkit | 已安装 Docker,以及支持 GPU 的 runtime(nvidia-docker / nvidia-container-runtime) | 这样才能让容器访问 GPU |
模型 / 权重访问权限 | 若使用 Hugging Face 上的模型,需要设置访问 token / 权限 | 通常是 HF_TOKEN 或 HUGGING_FACE_HUB_TOKEN 环境变量 |
主机资源 | 足够的显存 / CPU / 内存 / I/O | 大模型可能需要几十 GB 显存,或拆分多卡部署 |
网络 / 端口 | 服务端口(如 8000)开放;若在公网上部署需做好安全措施 | 防火墙 / 反向代理 / 认证等 |
3. 使用官方 Docker 镜像部署(简单路径)
这是最直接、快速的方式:
3.1 拉取镜像
docker pull vllm/vllm-openai:latest
或者指定某个版本标签(如 v0.9.1
):
docker pull vllm/vllm-openai:v0.9.1
你可以在 Docker Hub 上查看可用标签和版本信息。(Docker Hub)
3.2 启动容器
下面是一个典型的 docker run
命令示例:
docker run --runtime nvidia --gpus all \
-v ~/.cache/huggingface:/root/.cache/huggingface \
--env "HUGGING_FACE_HUB_TOKEN=<你的 HF 访问 token>" \
-p 8000:8000 \
--ipc=host \
vllm/vllm-openai:latest \
--model <模型标识>
解释各参数:
--runtime nvidia --gpus all
:使容器可以访问所有 GPU(需宿主机有 NVIDIA Container 支持)-v ~/.cache/huggingface:/root/.cache/huggingface
:把宿主机的 Hugging Face 缓存目录挂载到容器内,这样模型权重可以复用 / 避免重复下载--env "HUGGING_FACE_HUB_TOKEN=..."
:设置 HF 访问令牌,用于私有模型或访问受限模型-p 8000:8000
:把容器的 8000 端口映射到宿主机 8000--ipc=host
:使用主机的 IPC 共享内存,防止 PyTorch 进程间通信问题。你也可以选择使用--shm-size
来替代(如果不愿用ipc=host
)(VLLM Docs)vllm/vllm-openai:latest
:镜像名--model <模型标识>
:传递给 vLLM 的模型名称(比如mistralai/Mistral-7B-v0.1
)(VLLM Docs)
例如:
docker run --runtime nvidia --gpus all \
-v ~/.cache/huggingface:/root/.cache/huggingface \
--env "HUGGING_FACE_HUB_TOKEN=你的token" \
-p 8000:8000 \
--ipc=host \
vllm/vllm-openai:latest \
--model mistralai/Mistral-7B-v0.1
如果你是用 Podman 而不是 Docker,也可以类似运行:(VLLM Docs)
注意:你可以选择
--ipc=host
或者用--shm-size
参数来提供足够的共享内存给进程。vLLM 在 PyTorch 中使用共享内存(shared memory),所以如果内存太小可能会出问题。(VLLM Docs)
3.3 访问服务 / 接口
容器启动后,会在 http://<宿主机地址>:8000
启动一个 OpenAI 兼容的 API 服务,默认端点如下:
- 列出模型:
GET /v1/models
- 完成 (completions):
POST /v1/completions
- 聊天 (chat completions):
POST /v1/chat/completions
示例 curl 调用:
curl http://localhost:8000/v1/models
curl http://localhost:8000/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "mistralai/Mistral-7B-v0.1",
"prompt": "Hello, world",
"max_tokens": 20,
"temperature": 0.7
}'
如果你在你的应用程序中使用 OpenAI SDK(如 Python 的 openai
包),可以把 base_url
指向你的服务:
from openai import OpenAI
client = OpenAI(api_key="任意值", base_url="http://localhost:8000/v1")
resp = client.completions.create(model="mistralai/Mistral-7B-v0.1", prompt="你好", max_tokens=10)
print(resp.choices[0].text)
这样就像调用 OpenAI 一样。(VLLM Docs)
4. 从源码构建 / 自定义镜像
如果官方镜像不满足(比如需要额外依赖、支持某些 optional module、或者你想控制版本等),可以从源代码自行构建 Docker 镜像。
4.1 克隆源码 / 准备代码
从 vLLM 的 GitHub 仓库克隆:
git clone https://github.com/vllm-project/vllm.git
cd vllm
4.2 构建 Docker 镜像
在仓库目录下,有一个 docker/Dockerfile
,可以用这个 Dockerfile 构建包含 vLLM + OpenAI 接口的镜像:
DOCKER_BUILDKIT=1 docker build . \
--target vllm-openai \
--tag my-vllm-openai:latest \
--file docker/Dockerfile
如果你想调整构建参数(如并行编译数量、CUDA 架构优化等),可以使用 --build-arg
:
例如:
DOCKER_BUILDKIT=1 docker build . \
--target vllm-openai \
--tag my-vllm-openai:latest \
--file docker/Dockerfile \
--build-arg max_jobs=8 \
--build-arg nvcc_threads=2
或针对特定 GPU 架构做优化(减少不必要架构编译):
--build-arg torch_cuda_arch_list="你的目标架构"
构建完成后,你就得到一个镜像 my-vllm-openai:latest
,可以像前面那样用 docker run
启动。
注意:构建镜像可能比较耗时,编译过程也会占用较多显存 / 系统资源。(VLLM Docs)
如果你只打算微调或加入少量依赖,可以在官方镜像基础上继承。比如:
FROM vllm/vllm-openai:v0.9.0
RUN pip install vllm[audio]==0.9.0
这样在原有基础上添加 audio
可选依赖。(VLLM Docs)
5. 关键配置 / 参数说明
在运行 vLLM 服务时,有一些可调参数和注意点,下面整理常用 /重要的:
5.1 常用 CLI 参数
当你在 Docker 命令的末尾(或 vllm serve
命令中)传递参数,可以控制模型载入方式、类型、密钥、接口数量等。部分常见选项如下:
参数 | 说明 |
---|---|
--model <模型名称> | 指定要加载的模型,例如 mistralai/Mistral-7B-v0.1 |
--dtype <类型> | 指定模型权重的数据类型(如 auto 、fp16 、int8 等) |
--api-key <api_key> | 启用 API Key 验证(客户端请求必须带这个 Key) |
--host , --port | 指定服务监听地址与端口(默认 host = 0.0.0.0 , port = 8000 ) |
--config <config 文件路径> | 从 YAML 或 JSON 文件读取配置参数 |
--api-server-count / -asc | 并行启动多少个 API server 进程 |
--chat-template <路径或模板> | 如果模型没有默认 chat 模板,可以指定自己的模板文件 |
--generation-config <模式> | 控制是否使用模型自身的 generation_config.json (默认会使用) |
--headless | 无头模式(用于多节点 / 分布式场景) |
你可以在 vLLM 文档里查看完整参数列表和说明。(红帽文档)
5.2 共享内存 / IPC
正如前面提到的,vLLM / PyTorch 在内部可能使用共享内存(shared memory)用于多进程数据通信。如果容器的默认共享内存(/dev/shm
)太小,可能会遇错误(例如内存不足、进程间通信失败等)。因此通常建议:
- 使用
--ipc=host
(让容器共享主机的 IPC / /dev/shm) - 或者手动指定
--shm-size
,例如--shm-size=1g
/--shm-size=4g
等
(但 ipc=host
更安全 / 通常更稳定)(VLLM Docs)
5.3 模型缓存 / 权重下载
为了避免模型频繁重复下载和浪费网络 / I/O 资源,建议挂载一个持久缓存目录给容器(如 ~/.cache/huggingface
)。这样模型权重一旦下载过,下次重启可以复用。(VLLM Docs)
此外,要确保你的 HF 访问 token 有足够权限去下载所需模型(尤其是私有或受限模型)。通常 HUGGING_FACE_HUB_TOKEN
环境变量用于此目的。(Mistral AI 文档)
5.4 多模型 / 多任务支持
目前 vLLM OpenAI 接口服务在一个实例通常只承载一个模型(即一次只能加载一个模型运行服务)— 也就是说你在启动容器时,通常只指定一个 --model
。(VLLM Docs)
如果你需要多模型服务(即不同模型共存),你可能需要:
- 启动多个容器,每个容器挂载不同端口 /模型
- 或者自己扩展服务逻辑(修改 vLLM 源代码 /接口)
- 或者使用上层代理 /路由逻辑(如 NGINX / API Gateway)转发请求到不同模型服务
5.5 日志 / 性能监控
为了调试、监控服务状态,你可以考虑以下几点:
- 把容器日志导出或绑定日志目录
- 使用监控工具(如 Prometheus / Grafana)监测 GPU 利用率 / 内存 /请求延迟
- 为服务加上健康检查接口 / readiness probe
- 记录请求 /响应延迟 /错误率
6. 部署示例(Docker + Nginx + 简易 API 代理)
假设你要在一个公网服务器上部署 vLLM,并通过 Nginx 做反向代理(带 HTTPS、跨域、加 API Key 等),下面是一个示例架构与步骤。
6.1 架构思路
- 宿主机运行 Docker 容器,内部运行 vLLM 服务,监听 8000
- Nginx 作为前端代理,监听 443(HTTPS),把请求转发到容器
- Nginx 可做 SSL 证书、API Key 校验、流量控制、限流等
- 通常不直接把 8000 暴露给公网
6.2 步骤示例
- 部署 vLLM 容器:
docker run -d --name vllm \ --runtime nvidia --gpus all \ -v /path/to/hf_cache:/root/.cache/huggingface \ --env "HUGGING_FACE_HUB_TOKEN=你的 token" \ --ipc=host \ vllm/vllm-openai:latest \ --model mistralai/Mistral-7B-v0.1
- 安装 / 配置 Nginx(假设你有域名
api.example.com
): 示例 Nginx 配置片段:server { listen 80; server_name api.example.com; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name api.example.com; ssl_certificate /etc/nginx/ssl/fullchain.pem; ssl_certificate_key /etc/nginx/ssl/privkey.pem; location /v1/ { # 你可以在这里加 API Key 校验或 header 检查 proxy_pass http://127.0.0.1:8000; 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; } }
- 在客户端 /应用中使用:
- base_url 指向
https://api.example.com/v1
- 请求时在 headers 带上你希望校验的 API Key(如果你在 Nginx 或 vLLM 中做了校验)
- 同样遵循 OpenAI API 格式调用
/completions
//chat/completions
- base_url 指向
这样你的 vLLM 服务就变成一个相对安全、可接入公网的接口。
7. 注意事项 / 常见问题
在实际部署过程中,你可能会遇一些坑或需要警惕的点。下面列举一些经验与坑点:
- CUDA 兼容性 / 驱动不匹配
如果你的 GPU 驱动 / CUDA 版本与镜像内的 CUDA /内核不匹配,可能会出现 “no kernel image is available for execution on the device” 等错误。比如在 vLLM 的 Docker 镜像v0.9.0
上就有报告此类错误。(GitHub)
解决办法:使用与宿主机匹配的 CUDA 驱动版本、或者重新从源码构建适配版本。 - 共享内存不足
若没使用--ipc=host
或--shm-size
足够大,可能出现内部进程通信失败 / 内存错误。务必保证共享内存足够。 - 显存 / 内存不够
对于大型模型,单卡显存可能不够,或者多进程竞争导致 OOM,可以考虑减小批量大小、使用量化模型、或拆模型到多卡部署。 - 模型加载失败 / 权限问题
模型可能因为访问权限、token、网络问题导致加载失败。确保HUGGING_FACE_HUB_TOKEN
有正确权限,并且网络能访问 Hugging Face 仓库。 - API Key 安全 / 拒绝未授权访问
若你把服务暴露给外网,一定要设置 API Key 校验(可以在 vLLM 启动时用--api-key
参数)或者在 Nginx / 网关层做访问控制。 - 版本兼容 / Bug
vLLM 仍然在活跃开发中,Docker 镜像里可能有 bug 或与某些 GPU 架构不兼容。建议先在测试环境试通。 - 多模型支持
如前述,如果你需要同时提供多个模型服务,可能需要多个容器或自己扩展逻辑。
8. 完整示例(总结)
下面是一个总结版的部署示例:
# 1. 拉取镜像
docker pull vllm/vllm-openai:latest
# 2. 运行容器
docker run -d --name vllm-server \
--runtime nvidia --gpus all \
-v /home/ubuntu/hf_cache:/root/.cache/huggingface \
--env "HUGGING_FACE_HUB_TOKEN=你的token" \
-p 8000:8000 \
--ipc=host \
vllm/vllm-openai:latest \
--model mistralai/Mistral-7B-v0.1 \
--api-key 我的服务密钥
# 3. Nginx 配置(假设放在 /etc/nginx/sites-enabled/vllm.conf)
# …(如前所述)…
# 4. 重载 Nginx / 启用 SSL etc.
# 5. 客户端调用示例(Python)
from openai import OpenAI
client = OpenAI(api_key="任意值", base_url="https://api.example.com/v1")
resp = client.chat.completions.create(
model="mistralai/Mistral-7B-v0.1",
messages=[{"role":"user","content":"你好"}],
)
print(resp.choices[0].message.content)
发表回复