Docker搭建实验室GPU服务器环境

为什么使用docker

服务器主要的使用场景是科学计算,跑深度学习模型,有过单机配置训练环境的经历的人就知道,多版本CUDA共存有多不方便。

之前搭建服务器环境只是利用anaconda做了一个简单的环境控制,加上每个用户设置单独用户账号登录来管理自己的环境。后来当要复现一些老版本tensorflow代码的时候需要使用CUDA9,这时候之前搭建的环境就显得有点憨憨了,早就知道有个玩意叫docker,这次好好看了一下

并且通过学习寻陌千的博文 https://blog.csdn.net/hangvane123/article/details/88639279#comments
这篇博文,成功搭建了用nvidia-docker调度GPU资源的docker环境,以隔离开实验室成员之间不同的环境,这样通过不同的docker容器,使用者将不会面临环境冲突的问题,因为所有的环境都是独立的。

方案说明

  1. 宿主机选择Ubuntu16.04 LTS因为稳定
  2. 为了支持在虚拟机中使用GPU资源,使用nvidia-docker插件。
  3. 容器使用bridge方式联网,通过端口映射开放部分端口,与宿主机映射部分共用文件夹以方便文件传输。
  4. Docker日常管理使用Shipyard

整体流程

在安装完Ubuntu16.04后,跟换apt源

备份删除旧源

sudo mv /etc/apt/sources.list /etc/apt/sources.list.bak

写入新源

sudo vim /etc/apt/sources.list

将以下内容复制进去

deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-updates main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-updates main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-backports main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-backports main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-security main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-security main restricted universe multiverse

保存退出后

sudo apt-get update

禁止Linux内核更新

查看已安装的内核

sudo dpkg --get-selections | grep linux

禁止更新内核

sudo apt-mark hold linux-image-x.xx.x-xx-generic

以后如需要恢复更新

sudo apt-mark unhold linux-image-x.xx.x-xx-generic

安装显卡驱动

去 https://www.nvidia.cn/Download/index.aspx?lang=cn下载对应驱动,放到~目录下方便查找

然后卸载默认驱动(有可能没有卸载掉什么东西,但是不管就好)

sudo apt-get purge nvidia*

然后禁用nouveau

sudo vim /etc/modprobe.d/blacklist-nouveau.conf

写上如下内容

blacklist nouveau
options nouveau modeset=0

进行更新

sudo update-initramfs -u

结束X-window服务

sudo service lightdm stop

然后按Ctrl + Alt + F4进入tty4控制台,开始安装驱动

cd ~
sudo sh NVIDIA*(执行之前下载的nvidia驱动文件)

安装的时候会有一个32bit相关的警告不用理会,然后安装完后会提示是否更新X-windows配置要选yes

完毕后重启X-window

sudo service lightdm start

如果没有图像,按 Ctrl + Alt + F7 返回图形界面

测试熟悉的显卡信息

nvidia-smi

如果到这一步有错的话就只有重装驱动了

安装docker

为了提高速度,通过https,允许apt使用repository安装软件包

sudo apt-get install -y \
       apt-transport-https \
       ca-certificates \
       curl \
       software-properties-common 

添加Docker官方GPG key

curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | apt-key add -

验证key的指纹

apt-key fingerprint 0EBFCD88

添加稳定版repository

add-apt-repository \
   "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

更新apt包索引

apt-get update

安装最新版本的Docker CE

apt-get install -y docker-ce

验证Docker CE正确安装

docker run hello-world

之后不要急着配置Docker,因为安装nvidia-docker会覆盖daemon.json

安装nvidia-docker2

先添加repositories

curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \
  sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/ubuntu16.04/amd64/nvidia-docker.list | \
  sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update

安装nvidia-docker2并重新载入daemon.json

sudo apt-get install -y nvidia-docker2

加入docker组,以允许非root用户免sudo执行docker命令

sudo gpasswd -a 用户名 docker

如果不重启并重连ssh客户端的话,需要手动重启服务并刷新docker组成员

sudo service docker restart
newgrp - docker

Docker换源,换存储路径,限制容器日志大小

备份daemon.json

sudo cp /etc/docker/daemon.json /etc/docker/daemon.json.bak

修改daemon.json

sudo vim /etc/docker/daemon.json

安装完nvidia-docker后默认应该是这样

{
    "runtimes": {
        "nvidia": {
            "path": "nvidia-container-runtime",
            "runtimeArgs": []
        }
    }
}

修改默认运行时为nvidia-docker,添加国内源,修改存储位置为/home/docker,限制日志大小后daemon.json为

{
    "default-runtime": "nvidia",
    "runtimes": {
        "nvidia": {
            "path": "nvidia-container-runtime",
            "runtimeArgs": []
        }
    },
    "registry-mirrors":[
        "https://kfwkfulq.mirror.aliyuncs.com",
        "https://2lqq34jg.mirror.aliyuncs.com",
        "https://pee6w651.mirror.aliyuncs.com",
        "https://registry.docker-cn.com",
        "http://hub-mirror.c.163.com"
    ],
    "data-root": "/home/docker",
    "log-opts": { "max-size": "50m", "max-file": "1"}
}

保存退出,并在/home下建立docker文件夹

cd /home
mkdir docker

在重启前,建议一并更改下网络设置,否则使用bridge模式连接的Docker容器可能无法访问外网
禁用dnsmasq

vim /etc/NetworkManager/NetworkManager.conf 

加#号注释掉dns=dnsmasq

连着docker一起重启电脑

sudo restart network-manager
sudo restart docker

重启后使用docker info查看是否修改成功

...
Docker Root Dir: /home/docker
...
Registry Mirrors:
 https://kfwkfulq.mirror.aliyuncs.com/
 https://2lqq34jg.mirror.aliyuncs.com/
 https://pee6w651.mirror.aliyuncs.com/
 https://registry.docker-cn.com/
 http://hub-mirror.c.163.com/
 ...

至此,可以删除之前的docker存储目录了

安装Shipyard中文版

下载依赖镜像

docker pull rethinkdb
docker pull microbox/etcd
docker pull shipyard/docker-proxy
docker pull swarm
docker pull dockerclub/shipyard

将原先脚本修改为中文脚本

wget https://raw.githubusercontent.com/shipyard/shipyard-project.com/master/site/themes/shipyard/static/deploy

将官方脚本换成修改为中文版的脚本

grep -n shipyard:latest deploy
sed -i 's/shipyard\/shipyard:latest/dockerclub\/shipyard:latest/g' deploy

默认会用到8080端口和2375端口,如果不想使用这两个端口可以修改,这里我们改成18080与12375端口

vim deploy

Docker搭建实验室GPU服务器环境_第1张图片

运行安装脚本

sh deploy

安装成功如下

Docker搭建实验室GPU服务器环境_第2张图片

此时可以通过本机浏览器输入localhost:18080访问了

创建容器

首先使用

docker pull nvidia/cuda:10.1-cudnn7-runtime-ubuntu16.04

来获取含有CUDA和CUDNN的镜像,上面只是一个例子,具体镜像可以访问

https://hub.docker.com/r/nvidia/cuda

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4jqXMBxC-1582775603721)(/images/pasted-18.png)]
选择合适的镜像进行pull,pull下来之后创建容器,由于我这里采用自己生产的镜像(镜像名为cuda-base:10.0,已包含pytorch1.3 tensorflow2 tensorflow1.14三个基础环境),代码为

NV_GPU=0 nvidia-docker run -dit --restart=on-failure -v /home/docker-common-dir:/home/common-dir -p30810:22 --name=newContainer -h=LAB_VM cuda-base:10.0 /home/startup.sh

其中 -p参数后面表示把容器22端口(也就是ssh端口)映射到宿主机的30810端口,此后可以直接用宿主机ip+端口的方式访问容器。 -h参数是指
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-juVdDhTt-1582775603722)(/images/pasted-19.png)]这个显示的东西,可以不管或者个性化。 最后/home/startup.sh是表示使用这个startup.sh脚本。

配置容器环境

由于之前我已经配置好一个包含pytorch1.3 tensorflow2 tensorflow1.14的基于CUDA10.0的镜像,需要的朋友可以直接去我的docker hub上pull,稍后给出链接

对于没有配置好的容器,参照以下配置方法可以很方便地配置好容器的基础环境。

容器内的Ubuntu是一个非常精简的系统,缺乏包括ping vim等一系列常用指令,需要按照以下方式配置

更新apt源

apt-get update

如果一直卡在connect这里进行不下去,说明容器内无法连接外网,此时需要配置

退出容器命令行

exit

设置Linux内核允许IP转发

sudo sysctl net.ipv4.conf.all.forwarding=1

将iptables FORWARD 的值更从DROP更改为ACCEPT:

sudo iptables -P FORWARD ACCEPT

资料显示这里的两个配置不会持久化,每次重启都需要重新配置,需要将它们添加到start-up stript,但是笔者实测不需要重新配置。之后重新进入容器控制台执行apt-get update,应该可以执行成功了,如果又卡在一半的地方是在更新NVIDIA的源,需要检查网络环境是否能够连通NVIDIA的网站

安装vim

apt-get install vim

更换apt源

cp /etc/apt/sources.list /etc/apt/sources.list.bak
rm /etc/apt/sources.list
vim /etc/apt/sources.list

在这里粘贴清华源的内容

# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-updates main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-updates main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-backports main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-backports main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-security main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-security main restricted universe multiverse

# 预发布软件源,不建议启用
# deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-proposed main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-proposed main restricted universe multiverse

然后更新源

sudo apt-get update

安装ssh

apt-get install openssh-server

允许root远程连接

vim /etc/ssh/sshd_config

PermitRootLogin prohibit-password
修改为PermitRootLogin yes

为root设置密码

passwd root

如果是宿主机Ubuntu16.04,安装ssh服务应该会自行启动并且已经加入自启项,但是在容器内安装则不会自动启动,而且一般设置自启项的方法对Docker容器不起作用 ,需要按照如下方法设置启动脚本启动ssh服务

(此时可以通过ssh://root:密码@宿主机IP -p2345连接容器了)

service ssh start

创建启动脚本

cd /home
vim startup.sh

输入启动脚本内容

#!/bin/bash
service ssh start
/bin/bash

/bin/bash的作用是保持Docker容器的后台运行,使用-dit参数的时候会附加执行这个命令,但是当设置了启动脚本后就不会附加执行了,需要手动执行。

附加执行权限

chmod 777 shartup.sh

这样基本的环境就配置好了

docker容器内出现无法输入中文,查看中文字符出现乱码情况,解决方法:在启动脚本中加入更换编码指令

vim /etc/profile

追加export LANG=C.UTF-8保存退出

打包为镜像

为了便于以后新建虚拟机,将容器作为镜像打包

nvidia-docker commit -m "说明" -a "作者" cuda1 cuda-base:10.0

其中cuda1为容器的名字,cuda-base:10.0为镜像的名字和tag

用自己的镜像创建容器

首先新建一个公共目录

cd /home
sudo mkdir docker-common-dir

新建容器

NV_GPU=0 nvidia-docker run -dit --restart=on-failure -v /home/docker-common-dir:/home/common-dir -p30810:22 --name=newContainer -h=LAB_VM cuda-base:10.0 /home/startup.sh

其中NV_GPU环境变量是为了控制容器可访问的GPU,如果不加这个参数则容器可以访问全部的GPU。–restart=on-failure是为了设置容器随Docker自动启动。将宿主机的/home/docker-common-dir映射到了容器的/home/common-dir目录,便于和容器的文件传输,容器的文件存储以及容器之间的文件传输。最后跟的是启动脚本,如果不输入则每次容器启动都不会自动启动ssh服务。

如果一切正常的话,现在已经可以通过ssh客户端连接容器了。
写来提醒自己:利用本地镜像创建了容器过后如果无法通过ip:端口直接连接,需要先

docker exec -it 容器名 /bin/bash

从宿主机进入容器后,设置root密码

passwd root

设置密码后就可以访问了

致谢

在此特别感谢原博客博主寻陌千对我的一些问题提供了解答和帮助,原博客地址为

https://blog.csdn.net/hangvane123/article/details/88639279

你可能感兴趣的:(开发环境,docker,深度学习,docker,nvidia)