docker环境,vLLM 部署 Qwen3.8-27B

声明

内网测试环境,无法承诺在生产环境使用,仅供学习参考。全程操作无互联网。

vLLM 部署 Qwen3.8-27B 说明文档

本仓库用于通过 Docker Compose 在 GPU 服务器上部署 Qwen3.8-27B(OpenAI 兼容接口),并对接 newapi 统一对外提供服务。


环境描述

Ubuntu22

nvidia GPU设备多个

内网测试,无互联网

docker最新版本

采用模型qwen3.8-27B

一、说明(部署对象与关键结论)

模型 Qwen3.8-27B(HuggingFace Qwen/Qwen3.8-27B,bf16 原始权重)
权重体积 约 54GB(27B 参数 × 2 字节),单张 A100-40GB 装不下
部署策略 Tensor Parallel = 2(两张卡分摊权重,未量化、零质量损失)
镜像 vllm/vllm-openai:v0.29.0
容器名 ruichuang-qwen3.8-27B
使用 GPU 设备 2 + 3(部署时完全空闲,各 4MiB)
服务端口 宿主 8011 → 容器 8000
服务模型名 Qwen3.8-27B
重启策略 unless-stopped(崩溃/重启自动拉起)
对接方式 newapi 跨机同局域网直连

⚠️ 模型为 bf16,单卡 40GB 显存无法容纳。若未来要改回「单卡」,必须先做 4-bit/8-bit 量化生成新权重,再调整 --tensor-parallel-size 1--quantization 参数(见第四节「进阶调整」)。


二、准备环境

在目标 GPU 服务器(下文称 gpu01)上确认:

  1. Docker + Docker Compose v2

    bash 复制代码
    docker --version
    docker compose version
  2. NVIDIA Container Toolkit (让容器能调 GPU)

    bash 复制代码
    nvidia-smi          # 能看到 8 张 A100 即驱动正常
    docker info | grep -i nvidia   # 应能看到 nvidia runtime
  3. 模型权重已就位

    bash 复制代码
    ls /home/data/ruichuang/Qwen3.8-27B/model-*.safetensors

    路径必须与 compose 中挂载一致(见第三节 volumes)。

  4. 确认 GPU 2、3 空闲 (避免与其他任务抢卡)

    bash 复制代码
    nvidia-smi

    部署前 GPU 2、3 的 Memory-Usage 应为约 4MiB

  5. 物理机端口 8011 未被占用

    bash 复制代码
    ss -ltnp | grep 8011   # 无输出即可

三、Compose 配置说明

文件:docker-compose-ruichuang-qwen3.8-27b.yaml

字段 说明
name ruichuang-qwen3.8-27b Compose 项目名,影响容器网络前缀
image vllm/vllm-openai:v0.29.0 vLLM OpenAI 服务镜像(已确认真实可用版本)
container_name ruichuang-qwen3.8-27B 固定容器名,便于 docker logs/exec
runtime nvidia 使用 nvidia 容器运行时(本机 compose 的 gpus 字段仅支持 all,故走 runtime)
environment NVIDIA_VISIBLE_DEVICES=2,3 限定容器内仅可见 2、3 号 GPU(vLLM 的 TP=2 即用这两张)
shm_size 16gb 增大共享内存,避免多 worker 时 RuntimeError
ipc host 与宿主共享 IPC 命名空间,配合 shm 提升多进程效率
ports 8011:8000 宿主 8011 映射到容器 8000(vLLM 监听端口)
volumes /home/data/ruichuang/Qwen3.8-27B:/models:ro 只读挂载模型目录到 /models
restart unless-stopped 容器退出或宿主重启后自动拉起
pull_policy if_not_present 锁定 v0.29.0,避免被意外重新拉取覆盖
security_opt no-new-privileges:true 禁止容器内提权
cap_drop ALL 丢弃全部 Linux capabilities(若启动报 capability 错误可移除此项)
logging max-size 50m / max-file 3 日志轮转,防止长期运行撑满磁盘
healthcheck curl 带 key 探 127.0.0.1:8000/v1/models 复刻 newapi 真实检查(服务就绪+鉴权通过+模型已注册)才标记 healthy;start_period 600s。用 curl 而非 python:vLLM v0.29.0 镜像(基础 nvidia/cuda:13.0.3-base-ubuntu24.04)保证有 curlpython3,但无裸 python 别名 ,用 python -cnot found
command 见下 vLLM 启动参数(镜像 entrypoint 已含 vllm serve,此处只传参数)

command 参数逐项说明:

参数 说明
--model /models 模型目录(容器内路径)
--served-model-name Qwen3.8-27B + qwen3.8-27b 对外的模型标识(vLLM 大小写敏感,故同时注册大小写两个别名;newapi 填任一均可)
--host / --port 0.0.0.0 / 8000 容器内监听地址与端口
--dtype bfloat16 A100 原生支持,精度/速度均衡
--tensor-parallel-size 2 2 卡并行,必需(单卡放不下)
--gpu-memory-utilization 0.95 单卡可用显存比例,留 5% 余量
--max-model-len 131071 最大上下文 ≈128K
--max-num-seqs 8 最大并发序列数
--api-key sk-ruichuang-qwen38-27b-... 访问密钥,newapi 必须填相同值;内网环境直接内联明文
--enable-prefix-caching 复用前缀 KV,省算力
--reasoning-parser qwen3 思考链解析器;指定后 v0.29.0 即启用 reasoning(旧版 --enable-reasoning 开关已被移除,不要再加)
--enable-auto-tool-choice 启用函数/工具调用
--tool-call-parser qwen3_coder 工具调用解析器
--trust-remote-code 允许模型自定义代码(新架构常需)

安全与暴露面提示

  • 密钥 :内网环境,api-key 已直接内联到 compose 的 --api-key 行(明文)。若部署到公网或更严格环境,建议外置到 .env 并通过 ${VLLM_API_KEY} 注入。
  • 端口暴露8011 绑定宿主全网卡(0.0.0.0)。因 newapi 跨机直连必须可达,故靠「api-key 鉴权 + 防火墙仅放行 newapi 网段」双保险。切勿在公网无防护暴露此端口。
  • trust-remote-code:仅对可信模型(如官方 Qwen)开启;换成来源不明模型前请先评估。
  • 并发上限--max-model-len 131071 × --max-num-seqs 8 的 KV cache 超过显存,vLLM 会按可用显存自动限制实际并发(约 1~2 条长上下文),属正常行为,不会启动失败。

docker-compose-ruichuang-qwen3.8-27b.yaml完整配置

bash 复制代码
name: ruichuang-qwen3.8-27b

services:
  vllm:
    image: vllm/vllm-openai:v0.29.0
    container_name: ruichuang-qwen3.8-27B
    # 仅用空闲的 2、3 号 A100(TP=2 分摊 27B 权重,单卡 40GB 装不下 bf16)
    # 注:本机 compose 版本的 gpus 字段仅支持 "all",故用 nvidia runtime + 环境变量限定卡号
    runtime: nvidia
    environment:
      - NVIDIA_VISIBLE_DEVICES=2,3
    shm_size: 16gb
    ipc: host
    ports:
      # 监听宿主所有网卡;生产环境务必用防火墙仅放行 newapi 所在网段(密钥已鉴权,但最小化暴露面)
      - "8011:8000"
    volumes:
      - /home/data/ruichuang/Qwen3.8-27B:/models:ro
    restart: unless-stopped
    pull_policy: if_not_present
    # 镜像 entrypoint 已含 `vllm serve`,这里只传参数(与 docker run 等价)
    # 注意:--max-model-len 131071 × --max-num-seqs 8 的 KV cache 超过显存,
    #       vLLM 会按可用显存自动限制实际并发(约 1~2 条长上下文并发),不会启动失败。
    command:
      - --model
      - /models
      # 单条 flag 接多值(vLLM 语义:SERVED_MODEL_NAME [SERVED_MODEL_NAME ...]);
      # 重复写两条 --served-model-name 会被后者覆盖,导致只注册最后一个名。
      # 同时注册大写/小写,规避 newapi 大小写不一致的 404。
      - --served-model-name
      - Qwen3.8-27B
      - qwen3.8-27b
      - --host
      - 0.0.0.0
      - --port
      - "8000"
      - --dtype
      - bfloat16
      - --tensor-parallel-size
      - "2"
      - --gpu-memory-utilization
      - "0.95"
      - --max-model-len
      - "131071"
      - --max-num-seqs
      - "8"
      - --api-key
      - sk-ruichuang-qwen38-27b-86227ee6768a3b4dd1fb25fdff0ddbb1a0cebc064588fd2f
      - --enable-prefix-caching
      - --reasoning-parser
      - qwen3
      - --enable-auto-tool-choice
      - --tool-call-parser
      - qwen3_coder
      # 仅对可信模型开启;Qwen3.8 为新架构,需要执行仓库内自定义代码
      - --trust-remote-code
      # ===== 多模态(视觉)支持 =====
      # Qwen3.8-27B 是原生 VLM(架构 Qwen3_5ForConditionalGeneration,config.json 含 vision_config),
      # 无需任何「开启多模态」开关,vLLM 加载视觉模型即自动启用图片/视频理解。以下两项为可选调优。
      # 每个提示词最多图片数:vLLM 默认各模态 999(无封顶),此处显式限制以防客户端大量灌图打满显存/算力。
      # 注意:该值必须是合法 JSON 字符串(vLLM 用 json.loads 解析),不能写 image=1(实测报 cannot be converted to loads)。
      # 单图场景用 {"image": 1};多图场景按需调大(如 {"image": 4});带尺寸:{"image": {"count": 4, "width": 512, "height": 512}}
      - --limit-mm-per-prompt
      - '{"image": 1}'
      # 多模态处理器缓存(GiB):缓存已处理的图片特征,避免对相同图片重复预处理,加速重复图/多轮图场景。
      # vLLM 默认值即为 4;此处显式调大以真正发挥作用。注意总占用 = 本值 ×(API进程数 + data_parallel_size),
      # 当前 TP=2(dp=1)→ 约 本值×2 的主机内存。设为 0 关闭(不推荐)。
      - --mm-processor-cache-gb
      - "8"
    # ===== 生产加固 =====
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    logging:
      driver: json-file
      options:
        max-size: "50m"
        max-file: "3"
    healthcheck:
      # 已核对 vLLM v0.29.0 镜像构建记录:基础镜像 nvidia/cuda:13.0.3-base-ubuntu24.04,
      # 镜像内保证存在 curl 与 python3(/usr/bin/python3),无 wget、无裸 python 别名(此前用 python -c 直接 not found)。
      # 故采用 curl 探活(官方推荐范式,无引号嵌套陷阱):带 api-key 打 /v1/models,
      # 返回 2xx 即 服务就绪+鉴权通过+模型已注册;-f 使 4xx/5xx 也判失败。
      # 127.0.0.1 强制 IPv4(服务仅监听 0.0.0.0=IPv4,localhost 可能解析到 ::1 导致连不上)。
      test:
        - CMD-SHELL
        - >-
          curl -fsS --max-time 5
          -H "Authorization: Bearer sk-ruichuang-qwen38-27b-86227ee6768a3b4dd1fb25fdff0ddbb1a0cebc064588fd2f"
          http://127.0.0.1:8000/v1/models >/dev/null 2>&1 || exit 1
      interval: 30s
      timeout: 10s
      retries: 5
      start_period: 600s

# ============ newapi 对接要点 ============
# 1) 新增渠道,类型选「vLLM」(或 OpenAI 兼容)
# 2) Base URL: http://<gpu01内网IP>:8011/v1   (把 <gpu01内网IP> 换成 gpu01 在局域网的真实 IP)
# 3) API Key: sk-ruichuang-qwen38-27b-86227ee6768a3b4dd1fb25fdff0ddbb1a0cebc064588fd2f (与 --api-key 一致)
# 4) 自定义/模型名填: Qwen3.8-27B
# 5) 建令牌,把该模型分配给对应令牌即可调用
#
# 密钥管理:内网环境,api-key 已直接内联到本文件(--api-key 行);如需更稳妥可外置到 .env。
# 启动: docker compose -f docker-compose-ruichuang-qwen3.8-27b.yaml up -d
# 日志: docker compose -f docker-compose-ruichuang-qwen3.8-27b.yaml logs -f
# 状态: docker compose -f docker-compose-ruichuang-qwen3.8-27b.yaml ps   (看 health 列)
# 自检: curl http://localhost:8011/v1/models -H "Authorization: Bearer sk-ruichuang-qwen38-27b-86227ee6768a3b4dd1fb25fdff0ddbb1a0cebc064588fd2f"

四、如何调整配置

编辑 docker-compose-ruichuang-qwen3.8-27b.yaml 后,docker compose up -d 重新拉起即可生效(改 command 参数需重建容器:docker compose up -d --force-recreate)。

1. 换 GPU 卡

yaml 复制代码
runtime: nvidia
environment:
  - NVIDIA_VISIBLE_DEVICES=4,5      # 改成任意两张空闲卡,如 4,5 / 2,4

说明:本机 compose 版本的 gpus 字段仅支持 "all",无法指定卡号,因此用 runtime: nvidia + NVIDIA_VISIBLE_DEVICES 来选卡。

TP 卡数需与 --tensor-parallel-size 一致;当前为 2 卡,若改成 1 张必须先把模型量化(见进阶)。

2. 换宿主机端口

yaml 复制代码
ports:
  - "8012:8000"         # 前半改宿主机端口(8011~8015 可用段内)

3. 换模型路径 / 模型名

yaml 复制代码
volumes:
  - /新路径/Qwen3.8-27B:/models:ro
command:
  - --served-model-name
  - 自定义名字           # newapi 侧同步改

4. 调并发与上下文

yaml 复制代码
command:
  - --max-num-seqs
  - "16"                # 提高并发(多吃 KV cache)
  - --max-model-len
  - "262144"            # 上下文拉到 256K(需显存足够)

5. api-key 管理(当前为内联明文)

当前 compose 的 --api-key 行已直接写入明文 key(内网环境按需求内联)。如需更稳妥:

  • 改为外置:删除 --api-key 行,在 compose 加 env_file: [.env] 并把 key 写进 .envVLLM_API_KEY=...),再 docker compose up -d --force-recreate 重建。
  • 轮换密钥 :直接改 --api-key 明文(或改 .env)后重建容器,newapi 渠道同步改。
  • 内联明文请避免把 compose 文件转发到不可信环境或提交到公开 Git 仓库。

6. 进阶:改回单卡(需先量化)

单卡 40GB 无法直接跑 bf16。路线:用 llm-compressorautoawq 产出 4-bit 权重,再:

yaml 复制代码
gpus: "device=2"
command:
  - --tensor-parallel-size
  - "1"
  - --quantization
  - awq                # 或 compressed-tensors(fp8)

五、如何部署

  1. docker-compose-ruichuang-qwen3.8-27b.yaml 传到 gpu01(如 /home/data/ruichuang/ 或任意目录)。

  2. 在该目录执行:

    bash 复制代码
    docker compose -f docker-compose-ruichuang-qwen3.8-27b.yaml up -d
  3. 观察启动日志(模型加载约需 1~3 分钟):

    bash 复制代码
    docker compose -f docker-compose-ruichuang-qwen3.8-27b.yaml logs -f

    看到 Uvicorn running on http://0.0.0.0:8000 即服务就绪。

  4. 常用运维:

    bash 复制代码
    docker compose -f docker-compose-ruichuang-qwen3.8-27b.yaml ps       # 状态
    docker compose -f docker-compose-ruichuang-qwen3.8-27b.yaml down     # 停止
    docker compose -f docker-compose-ruichuang-qwen3.8-27b.yaml up -d --force-recreate  # 改配置后重建

六、部署后验证

容器启动后先等模型加载(约 1~3 分钟)。可用 docker compose -f docker-compose-ruichuang-qwen3.8-27b.yaml pshealth 列:从 startinghealthy 即就绪(健康探测为容器内置 curl 带 api-key 打 127.0.0.1:8000/v1/models,正是 newapi 实际依赖的检查,start_period 600s)。

health 列一直 unhealthy,用下面命令看探活真实输出定位根因:

bash 复制代码
docker inspect ruichuang-qwen3.8-27B --format='{{range .State.Health.Log}}{{.ExitCode}} {{.Output}}{{end}}'

正常应出现 0 + 空输出;若非 0,输出会直接给出原因(如 curl: not found、连接拒绝、401)。

1. 模型列表(需带 api-key)

bash 复制代码
curl http://localhost:8011/v1/models \
  -H "Authorization: Bearer sk-ruichuang-qwen38-27b-86227ee6768a3b4dd1fb25fdff0ddbb1a0cebc064588fd2f"

返回应包含 "id": "Qwen3.8-27B"

2. 一次对话测试

bash 复制代码
curl http://localhost:8011/v1/chat/completions \
  -H "Authorization: Bearer sk-ruichuang-qwen38-27b-86227ee6768a3b4dd1fb25fdff0ddbb1a0cebc064588fd2f" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen3.8-27B",
    "messages": [{"role": "user", "content": "用一句话介绍你自己"}],
    "max_tokens": 200
  }'

3. 确认 GPU 占用

bash 复制代码
nvidia-smi

GPU 2、3 的 Memory-Usage 应升至约 27GB+/卡,且出现 VLLM::EngineCore 进程。

4. 常见故障排查

现象 可能原因 处理
容器反复重启 显存不足 / 参数错 docker logs ruichuang-qwen3.8-27B 看堆栈
CUDA out of memory gpu-mem-util 过高或 max-num-seqs 过大 降到 0.90 / 调小 seqs
newapi 调不通 api-key 不一致 核对 compose 与 newapi 渠道 key 完全相同
推理很慢 KV cache 被 max-model-len 占满 适当下调 max-model-len

七、如何对接 newapi 使用

前提:newapi 与 gpu01 同局域网、可直连

  1. 登录 newapi 后台 → 渠道管理 → 添加渠道

  2. 渠道类型选 vLLM(或「OpenAI」兼容类型)。

  3. 填写:

    • Base URLhttp://<gpu01内网IP>:8011/v1
      (把 <gpu01内网IP> 换成 gpu01 在局域网的实际 IP,如 192.168.1.20
    • API Keysk-ruichuang-qwen38-27b-86227ee6768a3b4dd1fb25fdff0ddbb1a0cebc064588fd2f
      (即 compose --api-key 行内联的值,必须与之一致)
    • 模型 :填写 Qwen3.8-27B(自定义/支持的模型名)
  4. 保存并测试渠道连通性(newapi 有「测试」按钮)。

  5. 令牌管理 → 新建令牌 ,把 Qwen3.8-27B 分配给该令牌。

  6. 用 newapi 提供的「API 地址 + 令牌」即可像调用 OpenAI 一样使用该模型:

    bash 复制代码
    curl https://<newapi地址>/v1/chat/completions \
      -H "Authorization: Bearer <newapi令牌>" \
      -H "Content-Type: application/json" \
      -d '{"model":"Qwen3.8-27B","messages":[{"role":"user","content":"你好"}]}'

若 newapi 与 gpu01 不在同一台机,确保 gpu01 防火墙放行 8011 端口,且 <gpu01内网IP> 在 newapi 所在网络可达。

相关推荐
溜达的大象1 小时前
多台服务器不想上重型监控?用 Beszel 搭一套轻量主机与 Docker 看板
docker
正经教主2 小时前
【FDE系列】阶段2:Day 47:对接企业系统 — 飞书 / 钉钉 API
人工智能·docker·fde
九皇叔叔13 小时前
Kubernetes 资源管理方式详解:命令式与声明式管理
docker·容器·k8s
basketball61615 小时前
Python FastAPI 介绍以及常用方法
python·fastapi·vllm·ai infra
程序猿小郑19 小时前
Docker Compose 构建完整服务实战指南:从入门到最佳实践
docker·容器
论文复现现场21 小时前
RTX 3090 如何跑 13B 级大模型推理?4-bit AWQ、vLLM 部署与并发调优实战
模型量化·vllm·大模型推理·awq·算家云·rtx3090
行百里er1 天前
5 分钟跑起 Redis(Docker 版)
redis·后端·docker
Mr.朱鹏1 天前
Docker三剑客实战指南:Docker、Dockerfile 和 Docker Compose
python·docker·devops·dockerfile
鬼先生_sir1 天前
Docker 完整教程
docker