4、Docker 容器化环境搭建:Docker 与 Docker Compose 安装、拉取 PyTorch 官方镜像、编写 Dockerfile 定制环境、容器与宿主机文件/端口映射
说实话,搞大模型推理环境,最头疼的就是依赖冲突。
你装个 PyTorch,它要 CUDA 11.8;另一个项目非要 CUDA 12.1。来回折腾系统环境,我当年就吃过这个亏——有一次把显卡驱动搞崩了,重装系统花了一整天。后来我学乖了,所有项目都上 Docker。
Docker 说白了就是个轻量级虚拟机。但它比虚拟机快得多,因为它共享宿主机的内核。你想想看,一个容器启动只要几秒钟,资源开销几乎可以忽略不计。对于咱们搞大模型的人来说,Docker 能保证你的环境「一次构建,到处运行」。
4.1 Docker 与 Docker Compose 安装
先说说 Docker 怎么装。我个人习惯用官方脚本,省事。
# 一键安装 Docker(Ubuntu/Debian)
curl -fsSL https://get.docker.com | bash
# 验证安装
docker --version
# 把当前用户加入 docker 组,避免每次 sudo
sudo usermod -aG docker $USER
# 记得退出重新登录,或者执行 newgrp docker
嗯,这里要注意:如果你用的是 CentOS 或者 RHEL,官方脚本一样能用。但如果你在 Windows 上搞,我建议直接装 Docker Desktop,它自带 WSL2 后端,体验还不错。
Docker Compose 呢?它是用来编排多个容器的工具。比如你既要跑推理服务,又要跑数据库,用 Compose 可以一键启动所有服务。
# 安装 Docker Compose 插件(新版 Docker 自带)
docker compose version
# 如果没装,手动下载
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker compose(注意没有横杠)就行。别再用老版的 docker-compose 了,容易混淆。
4.2 拉取 PyTorch 官方镜像
Docker 装好了,下一步就是拉镜像。PyTorch 官方提供了很多预构建镜像,省得你自己从头装 CUDA、cuDNN 这些底层库。
# 拉取 PyTorch 官方镜像(带 CUDA 12.1)
docker pull pytorch/pytorch:2.1.0-cuda12.1-cudnn8-runtime
# 拉取 PyTorch 官方镜像(带 CUDA 11.8)
docker pull pytorch/pytorch:2.1.0-cuda11.8-cudnn8-runtime
# 查看本地已有镜像
docker images
为什么我要列两个版本?因为不同显卡对 CUDA 版本有要求。比如 RTX 4090 必须用 CUDA 12.x,而 RTX 3090 用 CUDA 11.8 更稳定。我在项目中遇到过,有人用 4090 强行装 CUDA 11.8,结果训练速度反而变慢了——因为驱动要来回做兼容转换。
-runtime 后缀的镜像只包含运行环境,适合部署;-devel 后缀的镜像包含开发工具链,适合编译自定义算子。如果你要跑推理,用 -runtime 就够了,镜像体积小一半。
4.3 编写 Dockerfile 定制环境
官方镜像虽然方便,但往往缺东西。比如你要装 transformers、accelerate 这些库,就得自己写 Dockerfile。
说白了,Dockerfile 就是一份「环境搭建说明书」。你告诉 Docker 要装什么、怎么装,它自动帮你构建镜像。
# 基础镜像:PyTorch 2.1.0 + CUDA 12.1
FROM pytorch/pytorch:2.1.0-cuda12.1-cudnn8-runtime
# 设置工作目录
WORKDIR /app
# 安装系统依赖(比如 git、wget)
RUN apt-get update && apt-get install -y \
git \
wget \
&& rm -rf /var/lib/apt/lists/*
# 安装 Python 依赖
RUN pip install --no-cache-dir \
transformers==4.36.0 \
accelerate==0.25.0 \
sentencepiece==0.1.99
# 复制项目代码到容器
COPY . /app
# 暴露端口(比如推理服务用 8000)
EXPOSE 8000
# 容器启动时执行的命令
CMD ["python", "inference.py"]
你可能会问:为什么用 --no-cache-dir?因为 pip 的缓存文件会增大镜像体积。我习惯在构建时加上这个参数,能让镜像小 200-300MB。
# 在 Dockerfile 所在目录执行
docker build -t my-inference-env:latest .
# 查看构建好的镜像
docker images | grep my-inference-env
4.4 容器与宿主机文件/端口映射
镜像构建好了,怎么跑起来?这里有两个关键概念:文件映射和端口映射。
文件映射:容器里的文件默认是隔离的,容器删了数据就没了。所以你要把宿主机上的模型文件、代码目录挂载到容器里。
端口映射:容器内部的服务(比如推理 API)默认只能在容器内访问。你要把容器的端口映射到宿主机,才能从外部调用。
# 启动容器,带文件映射和端口映射
docker run -d \
--name my-inference \
--gpus all \
-v /home/user/models:/app/models \
-v /home/user/data:/app/data \
-p 8000:8000 \
my-inference-env:latest
解释一下参数:
-d:后台运行--gpus all:让容器使用所有 GPU-v /宿主机路径:/容器路径:文件映射,冒号左边是宿主机,右边是容器-p 宿主机端口:容器端口:端口映射
/data/models 目录下,代码放在 /data/code 目录下。这样即使容器删了重建,模型不用重新下载,代码也不用重新拷贝。你想想看,一个 7B 的模型文件十几 GB,每次重建容器都重新拷贝,那得多慢。
如果你用 Docker Compose,可以写成 YAML 文件,更方便管理:
version: '3.8'
services:
inference:
image: my-inference-env:latest
container_name: my-inference
runtime: nvidia
volumes:
- /home/user/models:/app/models
- /home/user/data:/app/data
ports:
- "8000:8000"
environment:
- CUDA_VISIBLE_DEVICES=0,1
restart: unless-stopped
启动方式:
docker compose up -d
runtime: nvidia 可能不生效。需要先安装 nvidia-container-toolkit:
# 安装 NVIDIA 容器工具包
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
sudo systemctl restart docker
4.5 本章知识体系
下面这张图总结了 Docker 容器化环境搭建的核心流程:
整个流程其实就四步:装 Docker → 拉镜像 → 写 Dockerfile → 跑容器。每一步都有坑,但只要你按上面的步骤来,基本不会出问题。
我个人建议,刚开始接触 Docker 的同学,先别急着写复杂的 Dockerfile。先用官方镜像跑起来,看看效果,再慢慢加自己的依赖。这样出了问题也好排查——到底是镜像的问题,还是你加的东西有问题。
好了,这一章就到这里。记住:Docker 不是银弹,但它能解决 90% 的环境问题。剩下的 10%,嗯,那就要靠你慢慢积累了。