3、Docker基础与vLLM镜像:Dockerfile编写、构建vLLM推理镜像、推送镜像到私有仓库

说实话,很多刚接触K8s的朋友,第一步就卡在镜像上。

你想想看,K8s本身不跑代码,它只跑容器。容器从哪来?从镜像来。镜像怎么造?靠Dockerfile。所以这一章,咱们就把vLLM的镜像从零到一搞出来,再推到私有仓库里存着。这是后续所有部署工作的基础,绕不开的。

核心逻辑一句话:写Dockerfile → 构建镜像 → 推送到仓库 → K8s拉取运行。

Docker基础与vLLM镜像构建流程 ① 编写Dockerfile 基础镜像 + 依赖 + 入口 ② docker build 构建vLLM推理镜像 ③ docker push 推送到私有仓库 K8s 私有仓库推荐:Harbor / Docker Registry / 阿里云ACR 镜像命名规范:仓库地址/命名空间/镜像名:标签 💡 我建议:每次构建都打上明确的版本标签,别用latest

3.1 编写Dockerfile——从零搭一个vLLM推理环境

Dockerfile说白了就是一张「菜谱」。你告诉Docker:用什么锅(基础镜像)、放什么料(依赖)、最后怎么上菜(启动命令)。

我个人习惯,写Dockerfile之前先想清楚三件事:

  • 基础镜像选什么?——vLLM官方推荐用CUDA 12.x以上的镜像,因为要用到GPU。
  • 装哪些东西?——Python、PyTorch、vLLM包、还有你的模型文件(或者挂载路径)。
  • 启动命令是什么?——一般是 vllm serve 或者你自己写的入口脚本。

下面是我在实际项目中用过的一个Dockerfile,精简过,但核心骨架都在:

# 1. 基础镜像 —— 带CUDA的Python环境
FROM nvidia/cuda:12.2.0-runtime-ubuntu22.04

# 2. 设置工作目录
WORKDIR /app

# 3. 安装系统依赖
RUN apt-get update && apt-get install -y \
    python3 python3-pip git \
    && rm -rf /var/lib/apt/lists/*

# 4. 安装vLLM(这里指定版本,避免踩坑)
RUN pip3 install vllm==0.4.0

# 5. 复制你的启动脚本(如果有)
COPY entrypoint.sh /app/entrypoint.sh
RUN chmod +x /app/entrypoint.sh

# 6. 暴露端口(vLLM默认用8000)
EXPOSE 8000

# 7. 启动命令
ENTRYPOINT ["/app/entrypoint.sh"]

💡 我的经验:别把模型文件直接打进镜像里。镜像会变得巨大(动不动几十G),每次推送都痛苦。我一般用K8s的PVC或者HostPath挂载模型目录,镜像只装推理引擎。

3.2 构建vLLM推理镜像——docker build实战

Dockerfile写好了,接下来就是构建。命令很简单,但有几个细节我吃过亏,得跟你念叨念叨。

# 在Dockerfile所在目录执行
docker build -t vllm-inference:0.4.0 .

-t 是给镜像打标签,格式是 镜像名:版本号。我强烈建议你别偷懒用 latest,原因后面讲。

构建过程中,你会看到一层一层的输出。每一行 RUNCOPY 都会生成一个镜像层。层数太多会导致镜像臃肿,所以:

  • 能用 && 合并的 RUN 命令就合并
  • 用完的临时文件记得删掉(比如 apt-get clean

⚠️ 我曾经踩过的坑:有一次构建镜像时网络超时,pip下载vLLM包到一半断了。后来我加了 --timeout=120 参数,或者用国内镜像源(比如 -i https://pypi.tuna.tsinghua.edu.cn/simple),才稳定下来。

构建完成后,用 docker images 看一眼:

REPOSITORY        TAG       IMAGE ID       CREATED         SIZE
vllm-inference    0.4.0     abc123def456   2 minutes ago   3.2GB

嗯,3.2GB,正常。vLLM + CUDA runtime 本身就这个体量。

3.3 推送镜像到私有仓库——让K8s能拉到你

镜像在本地构建好了,但K8s集群里的节点怎么拿到它?你得推到一个仓库里。公有仓库(Docker Hub)速度慢,而且公司内部一般不允许。所以私有仓库是标配。

我常用的是Harbor,当然你也可以用阿里云ACR、华为云SWR,或者自建一个Docker Registry。流程都一样:

  1. 给镜像打上仓库地址的标签
  2. 登录私有仓库
  3. 推送
# 1. 打标签 —— 格式:仓库地址/项目名/镜像名:版本
docker tag vllm-inference:0.4.0 \
    harbor.internal.com/ai-team/vllm-inference:0.4.0

# 2. 登录
docker login harbor.internal.com
# 输入用户名和密码

# 3. 推送
docker push harbor.internal.com/ai-team/vllm-inference:0.4.0

关键点:K8s在拉取镜像时,会完全匹配这个地址。所以你在K8s的YAML里写 image: harbor.internal.com/ai-team/vllm-inference:0.4.0,它就能找到。

推送成功后,你可以在Harbor的Web界面看到镜像的详细信息,包括层数、大小、推送时间。我每次都会确认一下,确保没推错。

3.4 避坑指南——我替你们踩过的雷

这一节全是干货,都是真金白银换来的教训。

问题 原因 解决方案
镜像构建失败,提示CUDA版本不匹配 基础镜像的CUDA版本和vLLM要求的PyTorch版本冲突 去vLLM官方GitHub看Release Notes,找到对应的CUDA版本
推送镜像超时 镜像太大,网络带宽不够 分块推送(默认就是分层的),或者换内网仓库
K8s拉取镜像报错 ImagePullBackOff 镜像标签写错了,或者私有仓库没配Secret 检查YAML里的image字段,确保和推送时一致;配置 imagePullSecrets
容器启动后立刻退出 ENTRYPOINT脚本有问题,或者模型路径不对 先本地 docker run -it 调试,确认能正常启动再推

💡 一个小习惯:我每次构建完镜像,都会先在本地跑一下 docker run --gpus all vllm-inference:0.4.0,确认GPU能识别、模型能加载。这一步能省掉后面K8s排错的大量时间。

3.5 本章小结

到这一步,你已经掌握了:

  • 怎么写一个能用的Dockerfile
  • 怎么构建vLLM推理镜像
  • 怎么推送到私有仓库

说白了,镜像就是K8s世界的「可执行文件」。没有它,后面所有编排都是空谈。下一章我们会用这个镜像,真正在K8s上跑起一个推理服务。但今天先把基础打牢——镜像搞不定,后面全是坑。


专注资料整理