背景
最近要使用nvidia-docker2,并且使用docker-compose来编排nvidia-docker2的容器。
按照本文步骤执行前,你需要安装好:
- nvidia驱动:Kubuntu 16.04上安装Nvidia GPU驱动 + CUDA + cuDNN
- docker:Get Docker CE for Ubuntu
- 还需要安装好docker-compose: Install Docker Compose
重要更新:
如果你使用的是新版本的docker (>=19.03),则推荐使用nvidia-container-toolkit包来代替nvidia-docker2包:
# Add the package repositories
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
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 && sudo apt-get install -y nvidia-container-toolkit
sudo systemctl restart docker
当然nvidia-docker2包也可以继续使用,如果非得使用(比如k8s device plugin,再比如nvidia opengl实现),则继续往下看。
安装nvidia-docker2 的repo
1,安装nvidia-docker2的repo
其实,nvidia-docker 1.0也是同样的repo。
gemfield@ubuntu:~$ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
gemfield@ubuntu:~$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
gemfield@ubuntu:~$ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
gemfield@ubuntu:~$ sudo apt-get update
2,安装nvidia-docker2软件包
gemfield@ubuntu:~$ sudo apt-get install nvidia-docker2
gemfield@ubuntu:~$ sudo pkill -SIGHUP dockerd
3,配置daemon的默认运行时
因为gemfield需要在docker-compose中去编排nvidia docker 容器,因此需要设置docker的默认runtime为nvidia。在/etc/docker/daemon.json 文件中配置如下内容:
gemfield@ubuntu:~# cat /etc/docker/daemon.json
{
"default-runtime": "nvidia",
"runtimes": {
"nvidia": {
"path": "/usr/bin/nvidia-container-runtime",
"runtimeArgs": []
}
}
}
其实,在安装完成nvidia-docker2之后,nvidia-docker2已经默认在/etc/docker/daemon.json文件中写入了以下内容:
{
"runtimes": {
"nvidia": {
"path": "/usr/bin/nvidia-container-runtime",
"runtimeArgs": []
}
}
}
我们所做的工作其实就是在第一行加上了"default-runtime": "nvidia"。
你也可以设置代理来加快在国内的使用:
{
"default-runtime": "nvidia",
"runtimes": {
"nvidia": {
"path": "/usr/bin/nvidia-container-runtime",
"runtimeArgs": [],
"registry-mirrors": ["https://gemfield.mirror.aliyuncs.com"]
}
}
}
4,重启docker服务
gemfield@ubuntu:~$ sudo systemctl restart docker
#再次检查状态
gemfield@ubuntu:~$ systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2018-05-31 03:40:26 UTC; 40min ago
Docs: https://docs.docker.com
Main PID: 6514 (dockerd)
Tasks: 92
Memory: 44.2M
CPU: 36.471s
CGroup: /system.slice/docker.service
├─6514 /usr/bin/dockerd -H fd://
└─6527 docker-containerd --config /var/run/docker/containerd/containerd.toml
重创到来
1,错误信息
正当我们满欢喜悦准备庆祝的时候,灾难来了。在执行docker命令的时候:
gemfield@ubuntu:~$ docker run --runtime=nvidia --rm nvidia/cuda:8.0-cudnn6-runtime-ubuntu16.04 bash
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.real --device=all --compute --utility --require=cuda>=8.0 --pid=3741 /var/lib/docker/overlay2/4a727d26774c8508ad065790aa669d57f3a627c3664a8dc528d8b5967cad986c/merged]nnvidia-container-cli: initialization error: driver error: failed to process requestn""": unknown.
错误信息:nvidia-container-cli: initialization error: driver error: failed to process request。
2,看log信息
遇到这种问题,我们可以使用nvidia-container-cli -k -d /dev/tty info 来查看下具体的问题(或者使用命令nvidia-container-cli --debug=/dev/stdout list --compute):
gemfield@ubuntu:~$ sudo nvidia-container-cli -k -d /dev/tty info
-- WARNING, the following logs are for debugging purposes only --
I0531 09:38:43.912579 7397 nvc.c:274] initializing library context (version=1.0.0, build=163054a04b21c4455c8cae7e47873d9f2a091f55)
......
nvidia-container-cli: initialization error: load library failed: libcuda.so.1: cannot open shared object file: no such file or directory
......
很明显,错误原因就是libcuda.so.1: cannot open shared object file: no such file or directory。
3,确认错误
那么这个libcuda.so.1到底有没有呢?我们使用如下命令进行检查:
gemfield@ubuntu:~$ ldconfig -p | grep cuda
libicudata.so.55 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libicudata.so.55
果然没有这个库。libcuda.so.1这个库是来自于nvidia驱动,那为什么该系统上缺失呢?我们在有这个库的Ubuntu上使用dpkg -S命令来检查下它属于哪个package:
gemfield@ubuntu:~$ dpkg -S /usr/lib/x86_64-linux-gnu/libcuda.so.1
libcuda1-384: /usr/lib/x86_64-linux-gnu/libcuda.so.1
按道理说,安装驱动的时候会自动安装这个libcuda1-384包的,估计是什么历史遗留问题,或者是purge 又install把包的依赖关系搞坏了,因此现在需要重新安装。
庆祝
在经过手工安装libcuda1-384 package后,nvidia-docker命令可以愉快的运行了。我们又可以去解决下一个问题了。
gemfield@ubuntu:~$ sudo apt install libcuda1-384