Docker安装指南以及使用GPU
文章目录
随着公司GPU服务器数量的增加,深度学习开发环境的部署逐渐成为了负担。因为机器本身环境配置的差异,即使经验丰富的人也会遇到一些全新的问题,需要耗费时间去解决。而Docker与生俱来的Build once, Run anywhere
特点使得多机器统一环境部署变得极为容易,所以使用Docker势在必行
本文的主要内容为在腾讯云的GPU服务器上如何安装Docker,并能支持GPU的使用
(用了Docker后,就可以跟前文介绍的Anaconda拜拜了,因为conda只做到了Python环境隔离,并且每个虚拟环境还是要手动配置)
Docker是什么,有什么好处,网上的介绍很多,相关图书也有很多,在此不做赘述。我是通过《循序渐进学Docker》这本书入门的,让我很清晰的知道了基本概念和基本原理,摆脱了之前一看就头大的困扰
如果在网上搜索Docker相关的内容,经常会看到这个四个词:Docker、Moby、Docker-CE、Docker-EE
,所以在这里简单介绍一下这四个词之间有什么关系:
Docker于2013年3月正式开源,然后由社区正常进行版本迭代,一直至2017年3月版本为v1.13.1。然后Docker公司将Docker项目改名为Moby项目(仍由社区维护),并发布两款自己维护的产品Docker-CE和Docker-EE。其中Docker-CE为开源免费的,提供给广大开发者和用户使用;Docker-EE为封闭收费的,提供给企业级用户使用。现在大家口中的Docker主要指的就是Docker-CE
系列文章
本文为【Docker & Kubernetes & GPU】系列文章中的一篇:
- Docker安装指南以及使用GPU(本文)
- 使用Harbor搭建Docker私有仓库
- 基于Docker的Kubernetes-1.12集群搭建
- 在Kubernetes集群中使用GPU资源
环境配置
本文实践的服务器环境为:
- CentOS Linux release 7.5.1804 (Core)
- 内核版本:3.10.0-862.14.4.el7.x86_64
- 所安装的Docker-CE版本:18.06.1-ce
1、安装Docker
Docker需要使用root权限来安装。以下内容根据官方安装指南进行简化整理,完整版请移步:https://docs.docker.com/install/
官方指南中针对各个系统都有安装说明,此处使用的是CentOS。Docker CE要求使用CentOS 7版本,并且centos-extras
库需要启用,不过正常来说是默认启用的
卸载旧版本
1 | yum remove docker \ |
安装Docker CE
安装方式有许多种,这里选择使用添加yum库的方式来安装
安装相关依赖
1 | yum install -y yum-utils device-mapper-persistent-data lvm2 |
添加Docker的yum库
1 | yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo |
安装最新版Docker CE(安装时为18.06.1-ce)
1 | yum install docker-ce |
如果遇见无法安装的问题(跟audit-lib相关),请参考下方’一些错误’部分
如果提示需要接受GPG key,看一下是不是060A 61C5 1B55 8A7F 742B 77AA C52F EB6B 621E 9F35
,是的话就接受
如果要安装指定版本的,可以先执行yum list docker-ce --showduplicates | sort -r
列举出来所有版本,例如:
1 | docker-ce.x86_64 3:18.09.0-3.el7 docker-ce-stable |
然后执行yum install docker-ce-<VERSION STRING>
安装。其中<VERSION STRING>
指的是版本号中第一个破折号之前的内容,例如yum install docker-ce-18.06.1.ce
验证是否安装成功
启动Docker服务
1 | systemctl start docker |
如果报错,请参考下方’一些错误’部分
运行hello-world镜像
1 | docker run hello-world |
该命令会首先在本地寻找是否存在hello-world镜像,如果不存在就会去Docker官方镜像库Docker Hub中拉取下载,然后启动一个容器运行该镜像。如果成功运行,将会打印以下内容
1 | Hello from Docker! |
添加权限
执行Docker需要用户具有sudo权限,所以可以将需要使用Docker的普通用户加入docker用户组
先查看下是否存在docker用户组cat /etc/group | grep docker
(注意不是dockerroot),如果不存在则创建groupadd docker
。然后将普通用户添加至docker用户组中usermod -aG docker username
修改Docker Hub为国内镜像
参考自:https://www.docker-cn.com/registry-mirror
修改/etc/docker/daemon.json
文件(不存在则创建),并添加上 registry-mirrors 键值
1 | { |
转移数据目录
Docker的数据目录默认位于/var/lib/docker
,里面会存储着Docker镜像的数据。如果其所在的硬盘分区空间较小,可以将其转移到大的磁盘分区。例如我这里是根目录/
挂载在小硬盘上,/home
目录挂载在大硬盘上,所以将其转移到/home
目录下
1 | service docker stop |
安装Docker Compose
Docker提倡的理念是一个容器一个进程,那么一个服务是由多个进程组成的,那么就需要启动多个容器。而容器之间肯定是有依赖关系的(比如需要先启动数据库容器),如果手动管理则太麻烦。幸好Docker提供了一个工具——Docker Compose来解决这个问题,它允许用户在一个模版(yaml格式的)中定义一组相关联的容器,通过配置可以实现多个容器依次创建和启动
执行以下命令进行安装。其中1.23.1为撰文时的最新版本。可以去GitHub去查看最新版本
1 | curl -L "https://github.com/docker/compose/releases/download/1.23.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose |
执行docker-compose --version
验证是否安装成功
一些错误
- 跟audit-libs相关的依赖问题,错误内容如下
1 | 错误:软件包:audit-libs-python-2.8.1-3.el7.x86_64 (lianjia-base) |
看错误内容,是因为Docker所要依赖的包已经安装了,但是太新了不支持。所以需要卸载已安装的,然后安装Docker的时候自动安装所需要的版本。因为有很多包依赖了audit-libs,如果直接用yum进行删除会导致依赖audit-libs的包也被删除,所以这里使用rpm -e --nodeps xxx
的方式进行脱离依赖删除
执行rpm -e --nodeps audit-libs-2.8.1-3.el7_5.1.x86_64
后再安装Docker可能会提示下面的内容。这是因为服务器上安装了针对两个平台的audit-libs,只卸载一个的话,另外一个会被错误识别
1 | 错误: Multilib version problems found. This often means that the root |
那解决办法就是把支持另外一个平台的audit-libs也删除,执行rpm -e --nodeps audit-libs-2.8.1-3.el7_5.1.i686
,然后再yum install docker-ce
安装Docker就没问题了
- 执行
systemctl start docker
无法启动Docker服务,报错信息如下
1 | Job for docker.service failed because the control process exited with error code. See "systemctl status docker.service" and "journalctl -xe" for details. |
不论Docker服务因为什么原因无法启动都会报这个错误,具体的错误信息需要使用systemctl status docker.service
或者journalctl -xe
去查看,然后根据具体的错误再去解决(上网寻找资料)
执行journalctl -xe > error_info
将错误信息保存,便于查看。打开error_info,定位到Docker相关的部分。在这里我的最后的错误信息为:
1 | dockerd[3518]: Error starting daemon: Error initializing network controller: error obtaining controller instance: failed to create NAT chain DOCKER: iptables failed: iptables --wait -t nat -N DOCKER: iptables v1.4.21: can't initialize iptables table `nat': Table does not exist (do you need to insmod?) |
看起来是跟iptables和nat等网络有关的问题。再往上看会发现一堆nf_nat_ipv4: Unknown symbol nf_nat_l3proto_register (err 0)
类似的错误,再往上会看到最相关的初始错误:
1 | kernel: xt_conntrack: Unknown symbol nf_ct_l3proto_module_put (err 0) |
分析一下是因为无法加载xt_conntrack内核模块,而无法加载的原因是找不到nf_ct_l3proto_module_put
和nf_ct_l3proto_try_module_get
这两个内核符号
使用modinfo xt_conntrack
查看模块信息,可以发现其依赖于nf_conntrack。使用modprobe -v nf_conntrack
尝试加载,然后lsmod | grep nf_conntrack
检查是否加载成功,发现并没有输出相应信息。陷入困境。此处非常感谢 @武帅,指出可能是该模块被加入了黑名单,导致无法加载(自己完全没有考虑过还有模块加载黑名单的存在)。具体的解决办法为:
打开/etc/modprobe.d/blacklist.conf
文件,会看到其中跟nf_conntrack相关的内容
1 | # I/O dynamic configuration support for s390x (bz #563228) |
可以看到使用一系列网络相关的模块被blacklist关键字给屏蔽了,解决办法为将从nf_conntrack开始到nf_conntrack_ipv4之间的行加上注释
打开/etc/modprobe.d/connectiontracking.conf
,也会看到其中跟nf_conntrack相关的内容
1 | install nf_nat /bin/true |
这里的含义是如果发生install xxx
的行为,跳过加载过程直接返回install /bin/true
,所以也起到了加载模块屏蔽的作用。解决办法为将文件的后缀名进行修改,此处将其重命名为connectiontracking.conf.old
使其失效(或将文件内容全部加上注释)
然后再启动Docker服务systemctl start docker
,拉取hello-world镜像,成功。问题解决
2、安装Nvidia-Docker
安装好了普通的Docker以后,如果想在容器内使用GPU会非常麻烦(并不是不可行),好在Nvidia为了让大家能在容器中愉快使用GPU,基于Docker开发了Nvidia-Docker,使得在容器中深度学习框架调用GPU变得极为容易
以下内容根据官方安装指南进行简化整理,完成版请移步https://github.com/NVIDIA/nvidia-docker
官方指南中针对各个系统都有安装说明,因为使用的是CentOS 7,并且安装的Docker-CE,所以此处参照的是CentOS 7 (docker-ce), RHEL 7.4/7.5 (docker-ce), Amazon Linux 1/2
前置条件
- GNU/Linux x86_64 with kernel version > 3.10
- Docker >= 1.12
- NVIDIA GPU with Architecture > Fermi (2.1)
- NVIDIA drivers ~= 361.93 (untested on older versions)
一句话,只要安装了显卡驱动就可以(终于不用自己搞CUDA和cuDNN了)
显卡驱动下载链接:https://www.nvidia.com/Download/index.aspx
这里根据本机环境,各个选项的选择如下:
- Product Type: Tesla
- Product Series: P-Series
- Product: Tesla P40
- Operating System: Linux 64-bit
- Windows Driver Type: Standard
- CUDA Toolkit: 10.0
- Language: English(US)
其中CUDA版本选择最高的就行,因为支持高版本CUDA的驱动可以支持低版本CUDA,反过来不行
下载的文件名为:NVIDIA-Linux-x86_64-410.72.run
关于显卡驱动的安装可以参考之前的文章
删除旧版本
如果以前安装过nvidia-docker 1.0版本,需要先将其删除
1 | docker volume ls -q -f driver=nvidia-docker | xargs -r -I{} -n1 docker ps -q -a -f volume={} | xargs -r docker rm -f |
添加相关库
1 | distribution=$(. /etc/os-release;echo $ID$VERSION_ID) |
安装
1 | yum install -y nvidia-docker2 |
测试
1 | docker run --runtime=nvidia --rm nvidia/cuda nvidia-smi |
看到如下信息那便表示安装成功了
1 | +-----------------------------------------------------------------------------+ |
一些问题
- 安装完nvidia-docker后,之前配置使用Docker Hub国内镜像的那个文件(
/etc/docker/daemon.json
)内容可能会发生改变,需要检查并如有必要重新添加Docker Hub国内镜像 - docker: Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused “process_linux.go:402: container init caused \”process_linux.go:385: running prestart hook 1 caused \\”error running hook: exit status 1, stdout: , stderr: exec command: [/usr/bin/nvidia-container-cli –load-kmods configure --ldconfig=@/sbin/ldconfig –device=all –compute –utility –require=cuda>=10.0 brand=tesla,driver>=384,driver<385 –pid=46031 /home/dockerData/docker/overlay2/2965080837ad6a78dd0013f677706eac50d147e457a719281750755f7aecbdb1/merged]\\nnvidia-container-cli: requirement error: unsatisfied condition: driver < 385\\n\\”\””: unknown.
这个是在运行docker run --runtime=nvidia --rm nvidia/cuda nvidia-smi
时的报错。报错的关键信息为最后的requirement error: unsatisfied condition: driver < 385
,是说驱动不满足要求。这是因为在使用CUDA镜像的时候没指定tag,那么就会使用最新的,而最新版本的CUDA为10.0。出问题的这台服务器上安装的显卡驱动是当时为使用CUDA9安装的。所以问题就是因为现有的显卡驱动不支持CUDA10导致的
两种解决办法,一种是升级显卡驱动,如果要使用CUDA10可以这么做;另外一种是指定CUDA镜像的tag,因为目前的显卡驱动是支持CUDA9.0的,而此处运行该镜像也只是为了验证Nvidia-Docker是否安装成功,所以可以执行docker run --runtime=nvidia --rm nvidia/cuda:9.0-base nvidia-smi
,从而可以成功看到显卡信息
3、使用容器运行TensorFlow
接下来需要验证在容器中能否正常使用TensorFlow,参考自:https://www.tensorflow.org/install/docker
- CPU版
1 | docker run -it --rm tensorflow/tensorflow \ |
能输出TensorFlow的版本号便是成功,此处为1.11.0
- GPU版
1 | docker run --runtime=nvidia -it --rm tensorflow/tensorflow:latest-gpu \ |
能输出TensorFlow调用GPU的信息以及GPU数量便是成功,此处输出为
1 | 2018-11-02 10:02:03.213647: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA |
PS:添加-e NVIDIA_VISIBLE_DEVICES
参数可以指定容器使用哪一张(哪几张显卡),例如只使用第一张显卡
1 | docker run --runtime=nvidia -e NVIDIA_VISIBLE_DEVICES=0 -it --rm tensorflow/tensorflow:latest-gpu \ |
4、小结
至此完成了Docker的安装以及在容器内使用GPU
容器使用GPU并不会对其独占,多个容器使用GPU就如同多个程序使用GPU一样,只要协调好显存与计算力的使用即可
References
- 各类官方安装指南
- Docker:https://docs.docker.com/install/linux/docker-ce/centos/
- Nvidia-Docker:https://github.com/NVIDIA/nvidia-docker
- TensorFlow:https://www.tensorflow.org/install/docker
- 内核模块屏蔽相关