Ubuntu利用Docker进行深度学习,看这一篇就够啦!
网上有很多ubuntu利用docker配置深度学习环境的教程,但都不是很全,有的只有安装过程,有的只有某一些常用命令,我这里汇总一下。
sudo apt update
sudo apt install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
sudo apt update
sudo apt install docker-ce
好了,现在Docker已经安装完毕了,我们可以输出docker信息检查一下:
sudo docker info
如果此时输出了docker信息,则docker已经安装完毕了!
目前我们运行docker的时候,每句之前还都需要加上sudo,比较麻烦。我们可以利用添加用户到docker用户组的方式,让每次输入命令的时候不再需要在docker之前添加sudo。
sudo usermod -aG docker ${USER}
docker info
如果此时输出docker信息,说明已经成功加入docker组,以后docker命令前都不需要添加sudo了。一个Docker镜像小则百M大则数十G,国内从 DockerHub 拉取镜像速度很慢,建议配置镜像加速器。例如:科大镜像,阿里云等等。
以阿里云为例,首先需要一个阿里云账号,阿里云镜像获取地址:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors,登陆账号后,左侧菜单选中镜像加速器就可以看到你的专属地址了,形式如下:
https://XXX.mirror.aliyuncs.com/
当然也可以使用科大镜像(并不是专属的,直接复制就行):
https://docker.mirrors.ustc.edu.cn/
将你的镜像地址写入 /etc/docker/daemon.json 中(如果文件不存在则新建该文件):
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["此处填入你的镜像地址"]
}
EOF
重新启动服务:
sudo systemctl daemon-reload
sudo systemctl restart docker
此时我们就配好了docker镜像加速,可以更快的从DockerHub中拉取镜像。
使用如下命令查看Docker镜像与容器的默认存储位置:
docker info | grep "Docker Root Dir"
可以看到输出结果是/var/lib/docker
我们可以利用df -h
命令查看各个目录下的空间情况,一般/
下目录的空间不足以支撑深度学习镜像动辄10G+的空间占用,所以我们需要更改Docker默认存储位置到空间充足的目录,如/home
下的目录。
关闭docker服务(如有正在运行的容器请使用docker stop 容器名称
,关闭容器)
sudo systemctl stop docker.service
在你想存储的位置创建新的目录,并移动原来的镜像和容器到新的目录
mkdir /home/user/docker_data #此处替换为新的目录
cd /home/user/docker_data
sudo cp -r /var/lib/docker .
修改docker的配置文件,指定新存储位置
sudo vim /etc/docker/daemon.json
我们之前已经在这里添加了镜像加速,现在再在这里指定新的存储位置,修改为
{
"data-root": "此处填入新的存储位置",
"registry-mirrors": ["此处填入你的镜像地址"]
}
重新启动服务:
sudo systemctl daemon-reload
sudo systemctl restart docker
此时我们再查看Docker镜像与容器的默认存储位置:
docker info | grep "Docker Root Dir"
可以看到输出结果是我们自己指定的新位置。
至此我们已经安装好了docker,下面就可以正式操作docker了。
docker中和我们打交道的主要是 镜像 和 容器 两个概念,这里借用大佬的解释:
镜像:概念类似虚拟机的镜像。是一个只读的模板,一个独立的文件系统,包括运行容器所需的数据,可以用来创建新的容器。
容器:由docker镜像创建的运行实例。容器中会运行特定的运用,包含特定应用的代码及所需的依赖文件。可以把容器看作一个简易版的linux环境和运行在其中的应用程序。
以本人粗浅的理解,镜像就像是代码,是静态的,可以到处复制。容器就像是代码运行起来之后得到的程序,是动态的,就像我们可以和程序交互,我们也可以和容器交互。
如果要利用docker进行深度学习,一般来说,分以下几步:
此后的章节会根据以上步骤进行具体命令上的介绍。
docker命令使用包括传递一系列docker选项和命令,后跟参数。语法采用以下形式:
docker [option] [command] [arguments]
docker info
我们可以使用docker带子命令的search
命令搜索Docker Hub上可用的镜像,以搜索pytorch1.9相关镜像为例:
docker search pytorch1.9
当然也可以直接在Docker Hub的网页端搜索。
我们可以使用pull
命令拉取Docker Hub上可用的镜像,如:
docker pull lsg1213/pytorch1.9
镜像通常较大,可能需要拉取较长时间。
利用images
命令查看目前docker中存在的镜像
docker images
利用rmi
命令删除docker中的镜像
docker rmi image_name:tag_name
我们现在已经可以获取深度学习基础环境的镜像了,但是镜像是静态的,我们需要将其创建为容器,并在容器中对其进行进一步的配置,或者在其中运行网络获得结果。
镜像只是一个可读的配置文件,真正用来运行程序的是容器。对于我们本地的docker镜像,我们可以使用run
命令,将其创建为容器:
docker run -it --name 'Goodjob' lsg1213/pytorch1.9:v1 /bin/bash
参数说明:
-i
:交互式操作
-t
:终端
-name
:指定容器名称
'Goodjob'
:容器的名字
lsg1213/pytorch1.9:v1
:镜像名称:镜像标签(当镜像名称后面没有标签时,可以只写名称不写标签,此时docker会默认标签为latest
)
/bin/bash
:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash
在利用docker进行深度学习时,是要利用GPU资源的,然而常规的创建过程并不能使docker利用宿主机的GPU资源。目前版本的docker提供了gpus
参数供我们使用。
使得docker虚拟机可以访问宿主机全部的GPU资源时,我们使用--gpus all
:
docker run -it --name 'Goodjob' --gpus all lsg1213/pytorch1.9:v1 /bin/bash
使得docker虚拟机可以访问宿主机指定的GPU资源时,如第1,2块卡,我们使用--gpus '"device=1,2"'
:
docker run -it --name 'Goodjob' --gpus '"device=1,2"' lsg1213/pytorch1.9:v1 /bin/bash
注意:这里是单引号包双引号包device=x,漏掉其中任何一对引号都会报错。
我们可以让宿主机和容器共享代码目录,这样有两个好处:
利用v
参数共享目录:
docker run -it --name 'Goodjob' --gpus '"device=1,2"' -v out_path:container_inner_path lsg1213/pytorch1.9:v1 /bin/bash
参数说明:
-v
:共享目录
out_path
:宿主机路径
container_inner_path
:容器路径
注意:这里宿主机路径和容器路径都要采用绝对路径
当我们需要复制宿主机文件到容器时,可以利用cp
命令:
docker cp /home/out_path/a.py d9b132f2f636:/home/container_inner_path
参数说明:
cp
:复制命令
/home/out_path/a.py
:宿主机文件路径
d9b132f2f636
:容器id
/home/container_inner_path
:容器路径
当然,cp
命令也可以复制容器的文件到宿主机,将两个参数反过来就可以了:
docker cp d9b132f2f636:/home/container_inner_path/a.py /home/out_path
当使用run
命令,将容器创建起来后,我们会自动进入容器内部:
root@d9b132f2f636:/#
我们可以利用exit
命令退出容器,进入宿主机:
exit
在其他时候,我们使用attach
命令进入正在运行的容器
docker attach 容器名或容器ID
我们可以使用ps
命令查看运行的容器,使用ps -a
命令查看所有已经创建的容器:
docker ps -a
输出所有容器状态:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d9b132f2f636 lsg1213/pytorch1.9 "/bin/bash" About a minute ago Up About a minute Goodjob
当一个容器已经被创建,我们可以使用start
和stop
命令开启和停止容器。
开启容器运行:
docker start d9b132f2f636
停止容器运行:
docker stop d9b132f2f636
docker rename 原容器名称 新容器名称
docker rm 容器名称
现在我们已经可以在容器中运行深度学习代码并得到我们想要的结果了。但是这还没有结束,因为此后我们还可能有使用此容器的需求,或者我们可以将其分享给其他小伙伴,帮助他们更快的体验深度学习环境,这时就需要打包和分享镜像。
当我们在容器中配置好了深度学习环境,我们可能需要将其打包为镜像,在其他机器上运行,或者让其他人运行,此时就需要打包与分享镜像。
当我们想得到容器的镜像,以便在其删除后仍可以复现,或者想将其推送到Docker Hub时,我们使用commit
命令将容器打包(提交)为镜像。
docker commit -m "What you did to the image" -a "Author Name" container_id repository/new_image_name
参数说明:
commit
:提交命令
-m
:提交的注释
-a
:作者的名字
container_id
:容器的id
repository/new_image_name
:作者自定义的库名(一般和用户名一致)/镜像名
我们可以将自己的镜像推送到Docker Hub,供所有人下载使用。
注册Docker Hub,在Docker Hub网站https://hub.docker.com/signup
可以进行注册。
登录Docker Hub
docker login -u docker-registry-username
利用push
命令,要将名为image_name的镜像推送到你的存储库(假设你叫superman):
docker push superman/image_name
有时候我们的服务器并不能联网,不能从Docker Hub上pull镜像,我们就需要先从某个宿主机上将镜像导出,再在服务器上将镜像导入。
我们可以使用export
命令根据容器 ID 将镜像导出成一个tar文件:
docker export d9b132f2f636 > Goodjob.tar
可以看到文件已经保存到当前的 docker 终端目录下。
我们可以使用import
命令将tar文件导入为镜像:
docker import Goodjob_image < Goodjob.tar
Ps:如果有同时打包多个镜像到一个tar的需求,需要使用save
和load
命令进行镜像的导入和导出,大家可以自行查阅。
至此,我们已经学会了所有有关docker构建深度学习环境的知识,如有问题欢迎各位在评论区指出!