我想经常需要装环境的同学应该很烦,可能因为你的不小心,导致系统崩溃等等问题,或者环境需要装另一个版本的cuda,但是目前换可能不是很方便。这些我都遇到过,那么docker可以满足你的一切需求,你可以安装不同的环境,打包然后上传,下次就算是系统崩溃,也可以快速部署环境,不用浪费太多的时间,毕竟时间是最宝贵的。我在网上找了很多相关博客还是不会,然后结合大语言模型,和自己的实际操作,写了这篇文章,主要的目的是记录。那么接下来开始吧。
1. 编写Dockerfile
首先你需要创建一个名字为Dockerfile的文件,然后编写你需要安装的环境。我新装的ubuntu24.4,但是cuda官方只有cuda 12.6可以用,这样在测试一些东西的时候,环境又不匹配,那么利用docker可以安装不同版本的cuda。为了实现这一目的,写了如下的Dockerfile文件
bash
# 使用官方 Ubuntu 22.04 镜像作为基础镜像
FROM ubuntu:22.04
# 安装基本依赖
RUN apt-get update && \
apt-get install -y \
wget \
bzip2 \
gcc-12 \
g++-12 \
make \
curl \
gnupg \
lsb-release \
cmake \
neofetch \
net-tools \
vim \
openssh-server \
software-properties-common \
&& apt-get clean
# 将本地下载的 Anaconda 安装脚本复制到容器
COPY Anaconda3-2024.06-1-Linux-x86_64.sh /tmp/
# 安装 Anaconda
RUN bash /tmp/Anaconda3-2024.06-1-Linux-x86_64.sh -b -p /opt/anaconda && \
rm /tmp/Anaconda3-2024.06-1-Linux-x86_64.sh
# 将本地下载的 CUDA 文件复制到容器
COPY cuda-ubuntu2204.pin /etc/apt/preferences.d/cuda-repository-pin-600
COPY cuda-repo-ubuntu2204-12-4-local_12.4.0-550.54.14-1_amd64.deb /tmp/
COPY cudnn-linux-x86_64-8.9.7.29_cuda12-archive.tar.xz /tmp/
# 安装 CUDA
RUN dpkg -i /tmp/cuda-repo-ubuntu2204-12-4-local_12.4.0-550.54.14-1_amd64.deb && \
cp /var/cuda-repo-ubuntu2204-12-4-local/cuda-*-keyring.gpg /usr/share/keyrings/ && \
apt-get update && \
apt-get -y install cuda-toolkit-12-4 && \
rm /tmp/cuda-repo-ubuntu2204-12-4-local_12.4.0-550.54.14-1_amd64.deb
# 安装 cuDNN
RUN tar -xvf /tmp/cudnn-linux-x86_64-8.9.7.29_cuda12-archive.tar.xz -C /tmp && \
cp -P /tmp/cudnn-linux-x86_64-8.9.7.29_cuda12-archive/include/* /usr/local/cuda/include/ && \
cp -P /tmp/cudnn-linux-x86_64-8.9.7.29_cuda12-archive/lib/* /usr/local/cuda/lib64/ && \
chmod a+r /usr/local/cuda/include/cudnn*.h /usr/local/cuda/lib64/libcudnn* && \
rm -rf /tmp/cudnn-linux-x86_64-8.9.7.29_cuda12-archive
COPY TensorRT-10.4.0.26.Linux.x86_64-gnu.cuda-12.6.tar.gz /tmp/
# 安装 TensorRT
RUN tar -xzvf /tmp/TensorRT-10.4.0.26.Linux.x86_64-gnu.cuda-12.6.tar.gz -C /tmp && \
mv /tmp/TensorRT-10.4.0.26 /opt/ && \
rm /tmp/TensorRT-10.4.0.26.Linux.x86_64-gnu.cuda-12.6.tar.gz
# 安装其他依赖
ENV PATH=/usr/local/cuda-12.4/bin:$PATH
ENV LD_LIBRARY_PATH=/usr/local/cuda-12.4/lib64:$LD_LIBRARY_PATH
ENV PATH=/opt/anaconda/bin:$PATH
# 复制 requirements.txt 到容器
COPY requirements.txt /tmp/
# 创建 Conda 环境并安装依赖
RUN conda create -n pytorch python=3.10 --yes && \
conda run -n pytorch pip install torch torchvision torchaudio -i https://mirrors.bfsu.edu.cn/pypi/web/simple && \
conda run -n pytorch pip install -r /tmp/requirements.txt -i https://mirrors.bfsu.edu.cn/pypi/web/simple
# 激活环境
SHELL ["conda", "run", "-n", "base", "/bin/bash", "-c"]
# 设置工作目录
WORKDIR /home/only/workspace/deep_learning
# 默认命令
CMD [ "bash" ]
上述的文件不知道是否能看懂,其实你仔细看看,这不就是在Linux环境中经常使用的操作嘛,只是有docker自己特殊的写法而已。由于一些安装包需要拉取国外网站的东西,so 我下载到本地然后执行操作,相应的目录树如下所示:
c
.
├── Anaconda3-2024.06-1-Linux-x86_64.sh
├── cuda-repo-ubuntu2204-12-4-local_12.4.0-550.54.14-1_amd64.deb
├── cuda-ubuntu2204.pin
├── cudnn-linux-x86_64-8.9.7.29_cuda12-archive.tar.xz
├── Dockerfile
├── requirements.txt
└── TensorRT-10.4.0.26.Linux.x86_64-gnu.cuda-12.6.tar.gz
此时,进入到保存这些文件的文件夹,然后执行如下命令:
bash
docker build -t deepl_env .
因为我需要构建深度学习环境,所以我取得名字是deepl_env,记得最后的那个点
,重要,重要,重要
2. 启动编写启动脚本
bash
#!/bin/bash
# 这行指定了脚本的解释器为 `bash`,确保脚本使用 Bash shell 运行。
# 容器名称
CONTAINER_NAME="deeplearning-container"
# 定义一个名为 `CONTAINER_NAME` 的变量,用于存储容器的名称 `"deeplearning-container"`。
# 这个名称用于识别和管理 Docker 容器。
# 镜像名称
IMAGE_NAME="deepl_env"
# 定义一个名为 `IMAGE_NAME` 的变量,用于存储 Docker 镜像的名称 `"deepl_env"`。
# 这个镜像将用于创建容器。
# 端口映射
HOST_PORT=10008
CONTAINER_PORT=22
# 定义两个变量:`HOST_PORT` 和 `CONTAINER_PORT`。
# `HOST_PORT` 是主机上的端口号(10008),`CONTAINER_PORT` 是容器内的端口号(22)。
# 这行设置了端口映射,将主机的端口 10008 映射到容器的端口 22,通常用于 SSH 服务。
# 挂载路径
HOST_DIR="/home/only/workspace/deep_learning/"
CONTAINER_DIR="/opt/deep_learning"
# 定义两个变量:`HOST_DIR` 和 `CONTAINER_DIR`。
# `HOST_DIR` 是主机上的目录路径,`CONTAINER_DIR` 是容器内的目录路径。
# `-v ${HOST_DIR}:${CONTAINER_DIR}` 选项将主机目录挂载到容器内,使容器能够访问主机上的文件。
# 检查并删除同名的现有容器
if [ "$(docker ps -a -q -f name=${CONTAINER_NAME})" ]; then
echo "删除现有容器: ${CONTAINER_NAME}"
docker rm -f ${CONTAINER_NAME}
fi
# 检查是否已经存在名为 `${CONTAINER_NAME}` 的容器。
# 命令 `docker ps -a -q -f name=${CONTAINER_NAME}` 用于搜索该容器。
# 如果找到,使用 `docker rm -f ${CONTAINER_NAME}` 强制删除它。
# 这确保在启动新容器时不会发生冲突。
# 运行新的容器并保持它持续运行
echo "启动新容器: ${CONTAINER_NAME}"
docker run --gpus all -d -p ${HOST_PORT}:${CONTAINER_PORT} -v ${HOST_DIR}:${CONTAINER_DIR} --name ${CONTAINER_NAME} ${IMAGE_NAME} /usr/sbin/sshd -D
# 启动新的 Docker 容器:
# - `--gpus all`: 允许容器使用所有可用的 GPU。
# - `-d`: 以分离模式运行容器(在后台)。
# - `-p ${HOST_PORT}:${CONTAINER_PORT}`: 将主机端口 10008 映射到容器端口 22。
# - `-v ${HOST_DIR}:${CONTAINER_DIR}`: 将主机目录 `/home/only/workspace/deep_learning/` 挂载到容器目录 `/opt/deep_learning`。
# - `--name ${CONTAINER_NAME}`: 给容器指定一个名称。
# - `${IMAGE_NAME}`: 指定要使用的 Docker 镜像。
# - `/usr/sbin/sshd -D`: 在容器中运行 SSH 服务并保持它在后台运行。
# 检查容器是否启动成功
if [ $? -eq 0 ]; then
echo "容器启动成功,正在启动 SSH 服务..."
# 在容器中启动 SSH 服务
docker exec -it ${CONTAINER_NAME} service ssh start
echo "SSH 服务已启动,使用以下命令连接到容器:"
echo "ssh root@localhost -p ${HOST_PORT}"
else
echo "容器启动失败,请检查日志。"
fi
# 检查容器是否成功启动:
# - `$?`: 上一个命令的退出状态码。`0` 表示成功。
# - 如果容器启动成功,打印 `"容器启动成功,正在启动 SSH 服务..."` 并在容器内启动 SSH 服务,使用 `docker exec -it ${CONTAINER_NAME} service ssh start`。
# - 打印 SSH 连接信息,告知用户如何使用 SSH 连接到容器。
# - 如果容器启动失败,打印 `"容器启动失败,请检查日志。"` 并提示用户检查日志以获取更多详细信息。
我想通过vscode使用ssh连接内部的深度学习环境,那么我需要通过端口映射来实现,最终直接执行启动脚本,你将会得到如下输出:
bash
Removing existing container: deeplearning-container
deeplearning-container
Starting new container: deeplearning-container
ef996282380e664529f8caf9e953a3dee61ded0294007d6d5d2fd3d02ed9a639
Container started successfully, starting SSH service...
* Starting OpenBSD Secure Shell server sshd [ OK ]
SSH service started. Use the following command to connect to the container:
ssh root@localhost -p 10008
最后不管是终端还是vscode,通过ssh root@localhost -p 10008
连接就好,当然安装过程不止这些,还有很多的小细节,如果有需要可以互相交流联系。如果不对的地方,希望大佬指正。