1. Ubuntu 22.04 单机 Docker 部署 vLLM 与 OpenWebUI 时上游 Key 怎么统一
如果你手上只有一台 Ubuntu 22.04 的机器,想同时跑本地推理、网关和聊天前端,又不想在三个容器里各维护一套 Key,那这套组合值得试:vLLM 负责把 Qwen3-0.6B 跑成 OpenAI 兼容接口,New API 做统一网关,OpenWebUI 当聊天界面,最后把上游 endpoint 和 Key 收敛到 TaoToken 统一通道。它适合想自建 AI 工作台、又希望后续换模型或加渠道时不用改前端的人。
我这次用的环境是 Ubuntu 22.04、单张消费级显卡、Docker 24 以上、NVIDIA 驱动已装好。Qwen3-0.6B 体积小,单卡就能加载,适合先把链路跑通,再换成 Qwen3-8B 或更大的模型。整条链路的关键不是把三个容器都启动,而是让「前端 → 网关 → 推理/统一通道」的请求能逐层验证通过。很多人卡在 OpenWebUI 报reading choices或 New API 报local proxy failed,本质是中间某一层的 Base URL 或 Key 没对齐。
下面按「先跑通本地推理,再接入统一 Key,最后验证前端」的顺序来。每一步都有可复制的配置和验证命令,你可以边做边对照返回结果。
2. 用 Docker Compose 编排 vLLM、New API 与 OpenWebUI 的完整配置
先建目录,所有数据都放这里,方便备份和迁移:
mkdir -p ~/ai-stack && cd ~/ai-stack然后写docker-compose.yml。这份配置把三个服务放在同一个自定义网络里,容器之间用服务名互访,避免写死 IP:
services: vllm: image: vllm/vllm-openai:latest container_name: vllm restart: always runtime: nvidia ipc: host ports: - "8000:8000" volumes: - ~/.cache/huggingface:/root/.cache/huggingface environment: - HF_HUB_OFFLINE=1 command: > Qwen/Qwen3-0.6B --served-model-name qwen3 --host 0.0.0.0 --port 8000 --tensor-parallel-size 1 --gpu-memory-utilization 0.85 --max-model-len 4096 --max-num-seqs 64 new-api: image: calciumion/new-api:latest container_name: new-api restart: always ports: - "3000:3000" volumes: - ./new-api-data:/data depends_on: - vllm openwebui: image: ghcr.io/open-webui/open-webui:main container_name: openwebui restart: always ports: - "3001:8080" environment: - OPENAI_API_BASE_URL=http://new-api:3000/v1 - OPENAI_API_KEY=sk-替换成你的令牌 - ENABLE_OLLAMA_API=false - HF_HUB_OFFLINE=1 volumes: - ./openwebui:/app/backend/data depends_on: - new-api几个参数值得单独说。--served-model-name qwen3决定了接口里model字段该填什么,不设的话默认是模型全路径,请求时写qwen3会返回NotFoundError: The model 'qwen3' does not exist。--gpu-memory-utilization 0.85是留给模型和 KV Cache 的显存比例,剩下的留给系统和驱动。--max-model-len 4096是输入加输出的总上下文上限,Qwen3-0.6B 调大也行,但显存要跟上。ipc: host在多卡共享内存时很关键,单卡也建议保留。
模型文件建议先在宿主机下好,容器挂载缓存目录后直接离线加载,省得容器内网络不稳反复重试:
pip3 install -U huggingface_hub export HF_ENDPOINT=https://hf-mirror.com hf download Qwen/Qwen3-0.6B下载完成后文件会落在~/.cache/huggingface/hub/models--Qwen--Qwen3-0.6B/,和 compose 里的挂载路径一致。然后启动:
docker compose up -d docker compose ps等 vLLM 日志出现Uvicorn running on http://0.0.0.0:8000就说明推理服务起来了。第一次加载模型会慢一些,之后重启走缓存会快很多。
3. 把 New API 上游 endpoint 与 Key 改到 TaoToken 统一通道
这一步是整篇的重点。New API 的价值在于:前端只认一个 Base URL 和一个 Key,背后接的是本地 vLLM 还是统一通道,由网关决定。这样你换模型、加渠道、做额度统计,都不用动 OpenWebUI。
先访问http://你的IP:3000,第一次会进初始化页面,创建管理员账号。登录后进「渠道管理 → 新建渠道」。如果你只想先用本地 vLLM,类型选 OpenAI,API 地址填http://vllm:8000,模型填qwen3,密钥随便填一个(vLLM 默认不校验)。但既然目标是统一 Key,更推荐把上游指向 TaoToken 的 API 地址,这样本地和云端模型可以走同一个入口。
TaoToken 的 API 地址是https://taotoken.net/api,Key 在控制台的 API Keys 页面生成。渠道配置里:
{ "type": "openai", "name": "taotoken-unified", "base_url": "https://taotoken.net/api/v1", "api_key": "sk-你的TaoToken密钥", "models": "qwen3,qwen3-8b", "group": "default" }注意 Base URL 要带/v1,因为 OpenAI 兼容接口的路径是/v1/chat/completions。模型列表里可以同时写本地模型名和统一通道支持的模型名,New API 会按请求里的model字段路由。保存后点「测试渠道」,返回成功就说明网关到上游通了。
如果你更习惯用配置文件而不是界面,New API 的数据目录./new-api-data下会有持久化文件,但界面操作更直观,建议先用界面跑通再考虑导出。这里要提醒一句:不要把生产库直连到任何 MCP 或自动化脚本里,渠道配置属于敏感信息,改完记得确认没有把 Key 提交到 Git。
配好渠道后,进「令牌管理」创建一个令牌,得到sk-xxxxxxxx。这个令牌就是 OpenWebUI 要填的 Key,也是你对外调用统一通道时用的凭证。它和上游 TaoToken 的 Key 是两层,前端只接触这一层,上游 Key 留在网关里,安全性更好。
4. 逐层验证 vLLM 加载、网关转发与 OpenWebUI 对话
验证要一层一层来,哪层断了就修哪层,别一上来就开前端。
先验 vLLM 本身:
curl http://localhost:8000/v1/models返回里应该有"id":"qwen3"。再发一条聊天请求:
curl http://localhost:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{"model":"qwen3","messages":[{"role":"user","content":"你好"}]}'能看到choices里有回复内容,说明推理链路正常。Qwen3 会带<think>思考段,属于正常输出。
再验 New API 转发:
curl http://localhost:3000/v1/models \ -H "Authorization: Bearer sk-你的令牌"返回的模型列表里应该包含你在渠道里配的模型。再走一次聊天:
curl http://localhost:3000/v1/chat/completions \ -H "Authorization: Bearer sk-你的令牌" \ -H "Content-Type: application/json" \ -d '{"model":"qwen3","messages":[{"role":"user","content":"你好"}]}'如果这一步返回正常,说明「网关 → 上游」通了。最后打开http://你的IP:3001进 OpenWebUI,创建账号后进「管理员设置 → 外部连接 → OpenAI API」,填:
API URL: http://new-api:3000/v1 API Key: sk-你的令牌保存后刷新页面,模型下拉里应该能看到qwen3。发一条消息,能收到回复就说明三层全通了。如果 OpenWebUI 和 New API 不在同一个 compose 网络里,new-api要换成宿主机 IP。
5. 部署中常见报错排查:401、local proxy failed 与 reading choices
401 Unauthorized:最常见的是 Key 填错或没带Bearer前缀。检查 OpenWebUI 里的 Key 是不是 New API 的令牌,而不是 TaoToken 的上游 Key。curl 测试时确认-H "Authorization: Bearer sk-xxx"格式正确,冒号后有一个空格。
local proxy failed:New API 报这个通常是渠道的 Base URL 不通。如果填的是http://vllm:8000,确认两个容器在同一个 compose 网络里,且 vLLM 已启动。如果填的是 TaoToken 地址,确认网络能访问https://taotoken.net/api,以及 Base URL 带了/v1。容器内可以用docker exec -it new-api sh进去curl一下上游地址排查。
reading choices 报错:OpenWebUI 报这个一般是上游返回结构不对,常见原因是模型名不匹配。请求里model填的名字必须在渠道的模型列表里存在。比如渠道只配了qwen3,前端却发Qwen/Qwen3-0.6B,网关找不到就会返回错误结构。统一在渠道里把模型名对齐即可。
OAuth 相关报错:如果你给 OpenWebUI 配了第三方登录,回调地址和端口要对得上。单机测试阶段建议先用本地账号,别急着接 OAuth,减少变量。
模型加载失败:vLLM 日志里如果出现显存不足,把--gpu-memory-utilization调低到 0.7 再试,或者换更小的--max-model-len。如果是离线加载报找不到模型,确认HF_HUB_OFFLINE=1和缓存目录挂载都对,模型文件确实在~/.cache/huggingface/hub/下。
排查顺序建议固定为:先 curl vLLM,再 curl New API,最后看 OpenWebUI。哪层断修哪层,比同时改三个地方高效得多。
6. 统一 Key 之后:把 Coding Plan 与 API Keys 接进日常流程
链路跑通后,日常使用其实就两件事:拿 Key 和看文档。TaoToken 的 API Keys 页面用来生成和管理密钥,接入文档里有各语言和工具的调用示例。如果你主要做长期编码或 Agent 类任务,Coding Plan 更适合按周期使用;如果只是临时验证模型效果,直接用模型对话页面更快。
把统一 Key 接进编辑器或命令行工具时,记住三件套:Base URL 填https://taotoken.net/api/v1,Key 填控制台生成的密钥,Model ID 填渠道里配置的模型名。这三者对齐,基本不会出问题。本地 vLLM 和统一通道可以共存,网关按模型名路由,前端完全无感。这样一套单机 Docker 栈,既保留了本地推理的低延迟,又有了统一 Key 带来的可管理性。