前言
在深度学习的过程中经常会遇到对 CUDA 版本有不同要求的代码库,环境配置困难,本文尝试用 Docker 环境来解决此问题。
本文适用于 Ubuntu 系统,主要涵盖 Docker 安装、CUDA 镜像、PyCharm 使用 Docker 环境来调试和运行代码3个方面的内容。
一、Docker 安装
1. 卸载旧版本
在安装 Docker Engine 之前,需要卸载所有有冲突的软件包,然后才能安装 Docker Engine 的正式版本。
for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done
2. 添加密钥
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
补充
- 密钥的作用
GPG 密钥主要用于验证软件包的真实性和完整性。软件仓库在发布软件包时进行签名,用户通过秘钥验证签名。 - 镜像密钥
官网提供的密钥可能下不动,可使用镜像:
# 中科大
sudo curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
# 阿里云
sudo curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
-
指令解析
sudo curl -fsSL <url> | sudo apt-key add -
curl
命令从网站下载密钥,并传递给apt-key add -
将密钥添加到系统的全局密钥列表/etc/apt/trusted.gpg
。这种方式简单直接,但并不推荐,可能产生安全警告。sudo curl -fsSL <url> | sudo gpg --dearmor -o <file>
gpg --dearmor
将密钥由 ASCII 格式转换到二进制格式并存储到指定的文件中。sudo curl -fsSL <url> -o <file>
官方做法与第二种类似,只是密钥格式没有转二进制。先通过sudo install -m 0755 -d /etc/apt/keyrings
创建目录并设置了权限,下载密钥后再通过sudo chmod a+r /etc/apt/keyrings/docker.asc
为密钥文件添加读权限。
-
管理密钥
- 查看密钥
sudo apt-key list
- 删除密钥
sudo apt-key del 9DC858229FC7DD38854AE2D88D81803C0EBFCD88
- 查看密钥
/etc/apt/trusted.gpg
--------------------
pub rsa4096 2017-02-22 [SCEA]
9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88
uid [ 未知 ] Docker Release (CE deb) <docker@docker.com>
sub rsa4096 2017-02-22 [S]
3. 添加仓库
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
补充
- 镜像仓库
若使用了镜像密钥则需要添加镜像仓库,同样介绍一个不同的指令。
sudo add-apt-repository "deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
- 指令解析
- 镜像指令
add-apt-repository
将源添加到系统中,通常在/etc/apt/sources.list
或/etc/apt/sources.list.d/
中自动配置。[arch=amd64]
指定系统架构,$(lsb_release -cs)
对应 Ubuntu 版本代号,stable
指定软件发行版本。由于不能指定密钥位置,需要和sudo apt-key add -
一同使用。 - 官方指令
echo "..." | sudo tee <file> > /dev/null
将软件源配置写入到指定文件中。软件源配置与镜像指令类似,signed-by=<file>
指定密钥位置,$(. /etc/os-release && echo "$VERSION_CODENAME")
与$(lsb_release -cs)
基本相同。
- 镜像指令
4. 安装 Docker
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
5. 测试运行
sudo docker run hello-world
补充
很可能拉不动镜像,可在 /etc/docker/daemon.json
添加以下内容,配置 Docker 使用镜像加速器。最后一项阿里云的 ID 可在 镜像服务 → 镜像工具 → 镜像加速器中免费获取。
{
"registry-mirrors": [
"https://noohub.ru",
"https://huecker.io",
"https://docker.m.daocloud.io",
"https://dockerhub.timeweb.cloud",
"https://<id>.mirror.aliyuncs.com",
]
}
sudo systemctl daemon-reload
sudo systemctl restart docker
sudo docker run hello-world
6. 以非 root 身份管理 Docker
# 创建群组
sudo groupadd docker
# 添加用户
sudo usermod -aG docker $USER
# 激活更改
newgrp docker
# 测试
docker run hello-world
补充
- 群组管理
# 查看所有群组及其成员
getent group
# 查看指定群组的成员
getent group docker
# 删除用户(两种方式)
sudo deluser <username> docker
sudo gpasswd -d <username> docker
# 查看用户所属的所有群组
groups username
二、NVIDIA CUDA 镜像安装
NVIDIA Container Toolkit 官网安装指南
1. 安装
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
&& curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
所用指令与 Docker 安装大同小异,不再赘述。
2. 测试
sudo docker run --rm --runtime=nvidia --gpus all nvidia/cuda:11.6.2-base-ubuntu20.04 nvidia-smi
在 NVIDIA CUDA Docker Hub 中可以找一些官方的镜像进行测试,Tags 栏中可以进行检索。
3. 早期版本 CUDA
目前 Docker Hub 中最早的 CUDA 版本为 11.1.1,然而还有许多项目依赖更早版本的 CUDA。在 NVIDIA NGC 中可以查找更多版本。
sudo docker pull nvcr.io/nvidia/cuda:10.0-cudnn7-devel-ubuntu18.04
sudo docker run -i -t --gpus all nvcr.io/nvidia/cuda:10.0-cudnn7-devel-ubuntu18.04 /bin/bash
踩坑历程:
最初在 CUDA Image List 找到了可下载的镜像,使用 sudo docker load -i <image file>
读取镜像时报错 open /var/lib/docker/tmp/docker-import-4091194390/sources/json: no such file or directory
,最终查到原因是镜像在导出时有两种方法,save
对应 load
,export
对应 import
。
然而在加载镜像后创建容器却有异常。在查看压缩包内容后感觉可能是镜像缺少 Linux 的基础系统文件,暂未找到解决方案。
docker import nvidia-cuda-10.0-cudnn7-devel-ubuntu-18.04-x86_64.tgz cuda:10.0
sha256:49a9446b007887be75727da3cea0cbd57bb2c6fac84b98e6edac82e94ae8620c
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
cuda 10.0 49a9446b0078 9 seconds ago 2.43GB
docker run -it --gpus all cuda:10.0 /bin/bash
docker: Error response from daemon: failed to create task for container: failed to create shim task:
OCI runtime create failed: runc create failed: unable to start container process:
exec: "/bin/bash": stat /bin/bash: no such file or directory: unknown.
三、PyCharm 使用 Docker 环境
此功能必须使用专业版 PyCharm,下载及安装在此处。
1. 配置 Docker 服务器
如上图所示在 File -> Setting
页面点加号按默认方式配置 Docker 服务器(显示连接成功)。点击确定,如下图所示会弹出服务窗口,双击 Docker 启用后可以看到容器、镜像等信息。
2. 利用 SSH 使用 Docker 环境
此时可以在 PyCharm 中对 Docker 的镜像和容器进行操作,这里右键之前拉取的 CUDA10.0 镜像创建容器。在配置选项中,名称、挂载、入口点等按各自需求设置,运行选项中添加 --gpus all
使其可以使用 GPU,而绑定端口会与后续的环境使用密切相关。
绑定端口中,主机端口为 2222
,容器端口为 22
,协议为 tcp
,主机 IP 空缺。
以下内容并不充分,大致理解端口设置
- 主机端口
本地访问容器的服务时使用的端口号。这个端口必须在主机中是空闲的,不能和其他应用程序冲突。使用sudo ss -tuln
查看主机端口信息。- 容器端口
暴露到外部的容器服务端口,这个端口是容器中实际服务运行的端口。22
是默认用于 SSH 的端口,在容器中可以通过配置文件/etc/ssh/sshd_config
来修改默认端口号。- 协议
TCP 或 UDP,使用 SSH 网络服务使用 TCP 协议- 主机 IP
用于指定主机的网络接口(IP地址),默认(空缺)会将端口绑定到主机的所有网络接口(即0.0.0.0
)意味着可以从任何网络接口访问容器。通常用于设为内网 IP,使容器服务只对内网可见。
创建并启用容器,直接在 PyCharm 中打开容器终端并安装配置 SSH。
# 安装 SSH 服务
apt-get update
apt-get install -y openssh-server
service ssh start
# 查看 SSH 服务状态
service ssh status
# 配置 SSH 用户和密码
useradd -m <user_name>
passwd <user_name>
# 重启 SSH 服务
service ssh restart
下载 Miniconda 至挂载位置进行安装。默认安装位置为 /root/miniconda3
,由于 /root
文件夹的默认权限为 drwx------
会导致后续无法在 PyCharm 中使用 conda 的 python 环境,需要先修改权限 chmod 755 /root
。
如下图,添加 SSH 解释器,端口填写之前绑定端口中的主机端口,主机可以填写 127.0.0.1
或 0.0.0.0
或 0
。后两个是等价的,代表所有网络接口。127.0.0.1
代表本地主机 localhost 的回环地址,代表 SSH 服务就在本地系统上,不会通过网络接口。
用户名密码按前文配置的 SSH 用户名密码填写。解释器位置按需填写,例如 conda 的某个虚拟环境 /root/miniconda3/envs/env_name/bin/python
。至此,可使用 Docker 环境来对代码进行运行和 Debug。