4、Docker镜像制作:编写vLLM的Dockerfile、构建镜像并推送至仓库、优化镜像大小与启动速度、镜像安全扫描
说实话,Docker镜像制作这块,我见过太多人踩坑了。有人直接把整个Python环境打包进去,镜像几个G;有人图省事用latest标签,结果生产环境出了事都查不到版本。今天咱们就聊聊vLLM镜像怎么做才专业。
4.1 编写vLLM的Dockerfile
先说说我的习惯。我一般会从官方镜像开始,而不是从零搭建。为什么呢?因为vLLM依赖的CUDA、PyTorch版本组合很讲究,自己配容易出问题。
下面这个Dockerfile是我在项目中常用的,你可以直接拿来用:
# 基础镜像选择
FROM nvidia/cuda:12.1.0-runtime-ubuntu22.04 AS base
# 设置环境变量
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PIP_NO_CACHE_DIR=1 \
PIP_DISABLE_PIP_VERSION_CHECK=1
# 安装系统依赖
RUN apt-get update && apt-get install -y \
python3.10 \
python3-pip \
git \
build-essential \
&& rm -rf /var/lib/apt/lists/*
# 安装vLLM
RUN pip install vllm==0.4.0
# 设置工作目录
WORKDIR /app
# 复制入口脚本
COPY entrypoint.sh /app/
RUN chmod +x /app/entrypoint.sh
# 暴露端口
EXPOSE 8000
# 启动命令
ENTRYPOINT ["/app/entrypoint.sh"]
小提示:我建议把版本号写死,别用latest。有一次我在测试环境用了latest,结果第二天镜像更新了,模型推理结果全变了,排查了半天才发现是版本问题。
4.2 构建镜像并推送至仓库
构建镜像其实就一条命令,但这里有几个细节要注意:
# 构建镜像
docker build -t registry.example.com/vllm-server:0.4.0 .
# 打标签
docker tag registry.example.com/vllm-server:0.4.0 registry.example.com/vllm-server:latest
# 推送至仓库
docker push registry.example.com/vllm-server:0.4.0
docker push registry.example.com/vllm-server:latest
我个人习惯用docker buildx做多架构构建,特别是当你的K8s集群里有ARM节点时:
# 创建构建器
docker buildx create --name mybuilder --use
# 多架构构建并推送
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t registry.example.com/vllm-server:0.4.0 \
--push .
注意:推送镜像前,记得先登录仓库。我曾经因为忘记登录,构建了半小时的镜像白白浪费了。建议在CI/CD脚本里加上登录检查。
4.3 优化镜像大小与启动速度
镜像大小直接影响部署速度。你想想看,一个5G的镜像传到K8s节点上,那得等多久?
我常用的优化手段有这几个:
- 多阶段构建:把编译环境和运行环境分开
- 清理缓存:apt和pip的缓存能省不少空间
- 选择轻量基础镜像:比如用slim版本
来看一个优化后的Dockerfile:
# 第一阶段:构建
FROM python:3.10-slim AS builder
RUN pip install --user vllm==0.4.0
# 第二阶段:运行
FROM nvidia/cuda:12.1.0-runtime-ubuntu22.04
COPY --from=builder /root/.local /root/.local
ENV PATH=/root/.local/bin:$PATH
# 其他配置...
这样做的好处是,最终镜像只包含运行时需要的文件,构建时的中间产物全被丢弃了。我试过,镜像能从3.2G降到1.8G,效果很明显。
启动速度方面,我建议:
- 预加载模型权重到镜像里(如果模型不大)
- 使用
--shm-size参数设置共享内存 - 在K8s里设置
startupProbe,避免健康检查过早失败
经验之谈:我曾经遇到一个情况,镜像启动要5分钟,K8s一直重启Pod。后来发现是
livenessProbe设置得太早了。改成startupProbe后,问题就解决了。
4.4 镜像安全扫描
安全扫描这事,说白了就是给镜像做个体检。我一般用Trivy,开源免费,扫描速度也快。
# 安装Trivy
sudo apt-get install trivy
# 扫描镜像
trivy image registry.example.com/vllm-server:0.4.0
# 输出为JSON格式,方便集成到CI/CD
trivy image --format json --output result.json registry.example.com/vllm-server:0.4.0
扫描结果一般分几个等级:
| 严重级别 | 说明 | 我的处理方式 |
|---|---|---|
| CRITICAL | 可远程利用的漏洞 | 必须修复,否则不上线 |
| HIGH | 本地可利用的漏洞 | 尽量修复,评估风险 |
| MEDIUM | 需要特定条件 | 记录跟踪,定期复查 |
| LOW | 影响较小 | 忽略或后续处理 |
避坑指南:我曾经因为一个CRITICAL漏洞没修复,被安全团队卡了三天。从那以后,我都在CI/CD里加了扫描步骤,一旦发现高危漏洞就阻断构建。
另外,我建议把安全扫描集成到GitLab CI或Jenkins里,每次提交代码自动扫描。这样能尽早发现问题,而不是等到部署前才手忙脚乱。
嗯,镜像制作这块就聊到这儿。记住一个原则:镜像要小、启动要快、安全要过关。做到这三点,你的vLLM服务在K8s上就能跑得稳了。