# 从装驱动起步 在Ubuntu 18.04上构建GPU可用的Kaggle Docker镜像

> 作者：zning（https://ning.ae） · 发布：2019/07/14 20:24 下午 (UTC+8) · 原文：https://zning.me/15631070951540.html

接前文，在[安装好Ubuntu 18.04双系统](./15630136084061.html)和[解决了Windows与Ubuntu的时间同步问题](./15630143637063.html)后。正式进入正题了：构建GPU可使用的Kaggle Docker镜像(NVIDIA Only)。为了分享总结经验，同时也方便自己以后有使用需求，现简单总结下构建过程。

> 注意：本文首次撰写于2019-07-14，最近修改时间为2019-08-04，请注意相关程序的可用性与安全性。

> 前情提要：构建GPU可用的Kaggle Docker镜像需要挂载点`/`剩余至少50G，请自行斟酌设备是否能够支撑。

## 构建准备

### 安装NVIDIA驱动

> 本小结安装驱动因卡而异，本人所部署的机器的显卡为技嘉的P106-100，此款为矿卡不带显示输出。其对标的是GTX 1060 6G版。根据网上资料显示，其兼容GTX 1060的显卡驱动。因此如有不同请注意步骤可用性。如有疑问请查询资料或留言交流。

<!-- -->

> 本小节有相关显卡安装的有更简单的方案，具体可见参考文献4。请根据自己实际情况选择即可~

1. 按照显卡情况，在NVIDIA官网搜索下载。链接如下：

    1. 英伟达中国：https://www.nvidia.cn/Download/index.aspx?lang=cn
    2. NVIDIA Corporation：http://www.nvidia.com/Download/index.aspx?lang=en-us

    下载下来的驱动应该是后缀为`.run`的文件，放在一个路径合适的地方备用。

2. 卸载存量驱动，禁用`nouveau`驱动

    为防止显示崩溃，首先按`Ctrl+Alt+F1/F2/F6/F7`（组合键四选一）切换至纯命令行界面。
    
    之后，卸载存量驱动：
    
    ```shell
    sudo apt-get remove --purge nvidia*
    sudo apt-get autoremove --purge nvidia*
    ```
    
    然后，禁用`nouveau`驱动。通过以下命令打开下述文件：
   
    ```shell
    sudo vim /etc/modprobe.d/blacklist.conf
    ```
    
    最后一行加上：
    
    ```shell
    blacklist nouveau
    options nouveau modeset=0
    ```
    
    运行`sudo update-initramfs -u`命令使其生效，并`reboot`重启。重启后仍然按照上面要求进入纯命令行界面。

1. 安装新驱动
    
    输入命令`sudo service lightdm stop`暂停显示操作。
    
    > 但是我这里显示这个服务压根就没有，所以就不管了。

    进入之前下好的`.run`文件的所在目录，我这里放在了用户目录下，运行之。
    
    ```shell
    sudo sh ~/NVIDIA-Linux-x86_64-430.34.run
    ```
    
    后面就一路Accept就可以~
    
    报错`The distribution-provided pre-install script failed!`不必理会，继续安装。最重要的一步，安装程序问你是否使用nv的xconfig文件，这里一点要选yes，否则在启动x-window时不会使用nv驱动。
    
    重启桌面服务：
    
    ```shell
    sudo service lightdm start
    ```
    
    > 同刚才，我这个命令也运行失败了，但无妨。

    然后，`reboot`重启。
    
    > 注意：如果启动后无法进入桌面的情况（系统反复提示让你输入密码且不知疲倦）。请重复卸载所有NVIDIA驱动重新安装。99%解决此问题。

    输入`glxinfo | grep rendering`和`nvidia-smi`检查驱动安装情况。前者命令会出现`direct rendering: Yes`字样，后者会显示GPU列表。如果有问题请自行排查或重装驱动。

### 安装Docker-CE

安装https apt-get支持包，允许apt使用repository安装软件包：

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

添加Docker官方GPG key，并使用阿里镜像源。

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

通过搜索指纹的8个字符，验证key的指纹：`9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88`

```shell
sudo apt-key fingerprint 0EBFCD88
```

使用以下命令设置稳定的repository:

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

更新apt包索引并安装最新版本的Docker CE

```shell
sudo apt-get update  
sudo apt-get install -y docker-ce
```

或者在repository中列出可用的版本号，然后选择安装一个指定版本的Docker CE。

```shell
sudo apt-cache madison docker-ce
sudo apt-get install -y docker-ce=18.03.0~ce-0~ubuntu
```

安装后，Docker守护进程将会自动启动。

验证docker CE正确安装：

```shell
sudo docker run hello-world
```

### 安装nvidia-docker2

根据官方 https://github.com/NVIDIA/nvidia-docker 描述安装即可：

```shell
# 添加包管理源
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \
  sudo apt-key add -
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | \
  sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update

# 安装nvidia-docker2并重载docker daemon设置
sudo apt-get install -y nvidia-docker2
sudo pkill -SIGHUP dockerd

# 使用最新的官方CUDA镜像测试nvidia-smi
docker run --runtime=nvidia --rm nvidia/cuda:9.0-base nvidia-smi
```

## 开始构建

### 下载官方构建仓库

下载地址：https://github.com/Kaggle/docker-python

```shell
git clone https://github.com/Kaggle/docker-python.git
```

### 下载本地化构建`gpu.Dockerfile`

由于官方给的构建仓库中的`gpu.Dockerfile`部分镜像是需要翻墙访问的，为了方便内地使用，结合GDG Kaggle Shanghai社区群里王大佬分享的Dockerfile经验，形成了这个`gpu.Dockerfile`，文件如下：

如无法正常显示，请访问链接 https://gist.github.com/zning1994/dc98816a07f2f1339324964bc37ab429 。

<script src="https://gist.github.com/zning1994/dc98816a07f2f1339324964bc37ab429.js"></script>

说明一下，其中有两个文件为`article.tplx`、`base.tplx`，是我顺便解决了jupyter notebook导出中文的问题附带的，中文问题解决包括标题无法显示中文亦解决了，将在下一篇文章具体说明。为了在构建镜像时直接写入了镜像。在`gpu.Dockerfile`最后注释掉的代码是涉及此部分的，需要的童鞋可以删掉注释直接使用。将`article.tplx`、`base.tplx`放在官方构建仓库根目录即可。

下载此`gpu.Dockerfile`文件后，可覆盖官方文件，之后在官方构建仓库根目录运行下面命令进行构建。

```shell
sudo ./build --gpu
```

> 再此提醒：构建GPU可用的Kaggle Docker镜像需要硬盘空间剩余至少50G，请自行斟酌设备是否支撑。

<!-- -->

> 注意：构建需要大约个把小时，请去喝杯茶。

## 构建运行

> 构建完成后，`sudo ./test --gpu`执行可能会有错的，但是不妨碍使用，所以先不测试啦~

根据官方指导，可运行退出即删容器测试：

```shell
sudo docker run --runtime nvidia --rm -it kaggle/python-gpu-build /bin/bash
```

进去随便搞，自带jupyter，可通过运行`jupyter notebook --allow-root --ip="*" --notebook-dir=/tmp/working`运行jupyter notebook测试，不过浏览器是访问不了的，因为没有将容器端口映射到宿主机，因此我们可以运行如下命令启动直接运行jupyter notebook且映射端口的守护容器，此容器也会同宿主机启动时一同启动：

```shell
sudo docker run --restart=always --name kaggle --runtime nvidia -v /win/d/DeepLearning/pycharmProject:/tmp/working -w=/tmp/working -p 8888:8888 -itd kaggle/python-gpu-build jupyter notebook --allow-root --ip="*" --notebook-dir=/tmp/working
```

此时Ubuntu宿主机是可以打开浏览器访问`localhost:8888`进行访问啦~不过我们还不知道token，需要运行如下命令查看token连接：

```shell
sudo docker logs kaggle
```

## 附：Docker常用操作

> 所有命令均省略`sudo`

查看所有镜像：

```shell
docker images
```

查看所有容器：

```shell
docker ps -a 
```

查看守护容器日志：

```shell
docker logs 容器名或容器id
```

杀死所有正在运行的容器：

```shell
docker kill $(docker ps -a -q)
```

删除所有已经停止的容器：

```shell
docker rm $(docker ps -a -q)
```
删除所有未打 dangling 标签的镜像：

```shell
docker rmi $(docker images -q -f dangling=true)
```
删除所有镜像：

```shell
docker rmi $(docker images -q)
```
查找你需要的Docker镜像列表：

```shell
docker search mysql
```
下载镜像：

```shell
docker pull [REGISTRYHOST/][USERNAME/]NAME[:TAG]
```
容器转成镜像：

```shell
sudo docker commit <CONTAINER ID> imagename01
```
容器转成文件：

```shell
sudo docker export <CONTAINER ID> > /home/export.tar
```
镜像转成文件：

```shell
sudo docker save imagename01 > /home/save.tar
```
注：一般情况下，save.tar比export.tar大一点点而已，export比较小，因为它丢失了历史和数据元metadata。

文件转成镜像：

```shell
cat /home/export.tar | sudo docker import - imagename02:latest
save.tar文件转成镜像：
```

```shell
docker load < /home/save.tar
```
查看转成的镜像：

```shell
sudo docker images
```

## 参考文献

1. [GOG Kaggle Shanghai 社区群](#)
2. [Ubuntu 16.04 禁用 nouveau 安装 nvidia显卡驱动](https://blog.csdn.net/u012442845/article/details/78855573)
3. [Ubuntu16.04+Cuda8.0+Theano深度学习环境搭建一](https://www.jianshu.com/p/764edaff301e)
3. [Ubuntu 18.04 NVIDIA驱动安装总结](https://blog.csdn.net/tjuyanming/article/details/80862290)
4. [搭建nvidia-docker运行环境-Ubutu16.04](https://blog.csdn.net/arag2009/article/details/78464275)
5. [ubuntu安装Docker CE](https://blog.csdn.net/yjk13703623757/article/details/79865892)
6. [ocker容器、镜像相关命令](https://www.jianshu.com/p/9798e3ffc9a3)
