Dockerでデンソーのrosを動かす【NVIDIA Container Toolkit編】

# はじめに

前回、denso-robot-rosをDockerで動かすところまでこぎつけましたが、
GUIがおかしい状態でした。

前回記事：https://qiita.com/kineneticnamaco/items/2a7039200307c1fda0db

GUIがおかしいならGPUをちゃんと使えばいいじゃない？
ということでやってみたら動きました。

さて、DockerでGPUを使うためにはNVIDIAが出しているツールの導入が必要です。

ただ、Dockerが19.03からGPUにネイティブ対応した関係で、
必要なツールがnvidia-docker2からNVIDIA Container Toolkit（以下、toolkit）に変わっています。
参考：https://qiita.com/ksasaki/items/b20a785e1a0f610efa08
（追加ツールがいるのにネイティブ対応ってなんやねん、手間変わんねーじゃねーか。あと--gpusって言うならROCm対応しないとフェアじゃなくね？でも肝心のAMDはやる気なさそうだしなあブツブツ…）


ros公式にはnvidia-docker2を使うdockerイメージの作り方が説明されていますが、
「toolkitでも同じやろｗｗｗ」と思って進めたらコケました。

toolkitの記事もあんまりないので、一例として記事にします。

なお、なんでnvidia-docker2で動いてtoolkitで動かないのか原因はつかめていないので、
その手の話に詳しい人はまとめてくれると嬉しいです。


# できること

![Screenshot from 2020-01-30 21-39-41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549274/be5a017c-2f2b-d2d9-ba87-8daadf30f6d6.png)

前回は左の操作パネルなどが表示されてませんでしたが、今回は大丈夫です。


# 環境

|項目|バージョン等|
|---|---|
|CPU|Intel Core i7 860|
|GPU|NVIDIA GeForce GTX750Ti|
|Mem|8GB|
|OS|Ubuntu 18.04.3 64bit|
|Docker|19.03.5|
|GPU driver|NVIDIA Driver 440.33.01|

前と比べてGPUを変えました。

# 環境構築

コマンドだけさらっと紹介します。

## docker

```
curl -fsSL get.docker.com -o get-docker.sh
sudo sh get-docker.sh
```
参考：https://docs.docker.com/install/linux/docker-ce/centos/#install-using-the-convenience-script


## NVIDIA driver

```
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-ubuntu1804.pin
sudo mv cuda-ubuntu1804.pin /etc/apt/preferences.d/cuda-repository-pin-600
sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub
sudo add-apt-repository "deb http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/ /"
sudo apt-get update
sudo apt-get -y install cuda-drivers
```
参考:https://qiita.com/ksasaki/items/b20a785e1a0f610efa08#%E3%81%8A%E3%81%BE%E3%81%91-nvidia-%E3%83%89%E3%83%A9%E3%82%A4%E3%83%90%E3%83%BC%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB

## NVIDIA Container Toolkit

```
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
```

参考：https://github.com/NVIDIA/nvidia-docker/tree/master#quickstart

# やり方

というかDockerfile。

```:Dockerfile
FROM nvidia/opengl:1.1-glvnd-runtime-ubuntu16.04

RUN sh -c 'echo "deb http://packages.ros.org/ros/ubuntu xenial main" > /etc/apt/sources.list.d/ros-latest.list'
RUN apt-key adv --keyserver 'hkp://ha.pool.sks-keyservers.net:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654

RUN apt-get update
RUN apt-get install ros-kinetic-desktop-full ros-kinetic-denso-robot-ros -y

RUN echo "source /opt/ros/kinetic/setup.bash" >> /root/.bashrc

```

前回はosrfのイメージをもとにつくりましたが、
今回の発想は「GPUが動く保証のあるnvidiaのイメージから組み立てる」です。
あとrosの可視化ツールがopenglを使ってそうなので、openglイメージを使いました。
これじゃないと動かないかは試してません。

前回からの違いは、ROSのリポジトリ追加です。
これがないと目当てのパッケージがインストールできません。

あとは、ビルドして、

```:bash
$sudo docker build . --tag nv_opengl_ros
```

コンテナからxへのアクセスを許可して、

```:bash
$xhost + local:root
```

コンテナを立ち上げて、

```:bash
$sudo docker run -ti --rm --name master -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$DISPLAY -e QT_X11_NO_MITSHM=1 --gpus all nv_opengl_ros /bin/bash
```

rosを実行します。

```:bash
#roslaunch denso_robot_gazebo denso_robot_gazebo.launch
```

これで最初に紹介した画面が立ち上がるはずです。
環境によっては時間がかかるのでのんびり待ちましょう。

# その他

## 詰まったポイント

公式にnvidia-docker2を使う方法が説明されてます。
http://wiki.ros.org/docker/Tutorials/Hardware%20Acceleration

そこに習って作ってみてうまく行かなかったDockerfileが以下になります。

```:Dockerfileあかんやつ
FROM osrf/ros:kinetic-desktop-full

RUN apt-get update
RUN apt-get install ros-kinetic-denso-robot-ros -y
RUN apt-get install ros-kinetic-denso-launch -y

ENV NVIDIA_VISIBLE_DEVICES ${NVIDIA_VISIBLE_DEVICES:-all}
ENV NVIDIA_DRIVER_CAPABILITIES ${NVIDIA_DRIVER_CAPABILITIES:+$NVIDIA_DRIVER_CAPABILITIES,}graphics

RUN echo "source /opt/ros/kinetic/setup.bash" >> /root/.bashrc
```
走らせてもGPUを起こしてる途中で即落ちます。ターミナル抜粋。

```:bash
libGL error: No matching fbConfigs or visuals found
libGL error: failed to load driver: swrast
```

困ったときは公式を確認。すると

>What do I have to install in my container images?

>Library dependencies vary from one application to another. In order to make things easier for >developers, we provide a set of official images to base your images on.

「こまけーことはいいからnvidiaの公式イメージをベースにしろ」という話だったので素直に従いました。


# おわりに

UMPCきになるなあ・・・


# 参考文献
https://github.com/NVIDIA/nvidia-docker/wiki

# 変更履歴
- 2020/3/3 最後のところで動かないバグがあったので修正