Jetson NanoでDockerを動かす(前編)

# はじめに

Jetson NanoのJetPack 4.2には最初からdockerコマンドが含まれている。Dockerはx86系だけのものと思っていたので試すことにした。もしDockerからGPUが使えるのであればDockerにシフトしたい。

本記事の後に「[Jetson NanoでDockerを動かす(後編)](https://qiita.com/yamamo-to/items/51bfb92a00033257f02a)」と「[Jetson NanoでDockerを動かす(実践編)](https://qiita.com/yamamo-to/items/3022567ae054af495cf6)」を追加した。

# sudo不要の設定

Dockerコマンドを使うとき、使うユーザが`docker`グループに含まれていないと都度sudoを行う必要があり面倒である。そこで自分のユーザを`docker`グループに入れる。dockerサービスの再起動と再ログインを行うとsudoなしで使えるようになる。

```bash:ターミナル
sudo gpasswd -a $USER docker
sudo systemctl restart docker.service
exit # ここで一旦ログアウト
```

# クジラと遊ぶ

dockerを最初に使うときにはシンボルの「クジラ」のイメージ`whalesay`を試すのが通例である。

```bash:ターミナル
docker run docker/whalesay cowsay boo
```

以下、実行結果。

```bash:ターミナル
yamamo-to@jetson-nano:~$ docker run docker/whalesay cowsay boo
Unable to find image 'docker/whalesay:latest' locally
latest: Pulling from docker/whalesay
e190868d63f8: Pull complete 
909cd34c6fd7: Pull complete 
0b9bfabab7c1: Pull complete 
a3ed95caeb02: Pull complete 
00bf65475aba: Pull complete 
c57b6bcc83e3: Pull complete 
8978f6879e2f: Pull complete 
8eed3712d2cf: Pull complete 
Digest: sha256:178598e51a26abbc958b8a2e48825c90bc22e641de3d31e18aaf55f3258ba93b
Status: Downloaded newer image for docker/whalesay:latest
standard_init_linux.go:211: exec user process caused "exec format error"
```

クジラと遊ぶだけなのに`exec format error`とは・・・。こんなことは初めてだ。
とりあえずコンテナを全て表示させてみる。

```bash:ターミナル
yamamo-to@jetson-nano:~$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
f5d29ba92963        docker/whalesay     "cowsay boo"        5 minutes ago       Exited (1) 5 minutes ago                       youthful_hugle
```

コンテナとしては存在しているようだ。

クジラと遊びたいのでgithubからwhalesayを持ってくる。Dockerに関するファイルは全部ディレクトリ`$HOME/Documents/Docker`以下で行うことにする。

```bash:ターミナル
yamamo-to@jetson-nano:~$ mkdir ~/Documents/Docker/
yamamo-to@jetson-nano:~$ cd ~/Documents/Docker/
yamamo-to@jetson-nano:~/Documents/Docker$ git clone https://github.com/docker/whalesay.git
yamamo-to@jetson-nano:~/Documents/Docker$ cd whalesay
yamamo-to@jetson-nano:~/Documents/Docker/whalesay$
```

イメージをビルドする。タグはとりあえず「whale」にする。

```bash:ターミナル
yamamo-to@jetson-nano:~/Documents/Docker/whalesay$　docker build -t whale .
Sending build context to Docker daemon  205.8kB
Step 1/5 : FROM alpine
 ---> 1a773c1b496c
Step 2/5 : RUN apk add --no-cache perl
 ---> Using cache
 ---> 8a39a9c982ec
Step 3/5 : COPY cowsay /usr/local/bin/cowsay
 ---> 2e944ab746e4
Step 4/5 : COPY docker.cow /usr/local/share/cows/default.cow
 ---> 8f9d355e4f05
Step 5/5 : ENTRYPOINT ["/usr/local/bin/cowsay"]
 ---> Running in deb26be98488
Removing intermediate container deb26be98488
 ---> d142ce68452a
Successfully built d142ce68452a
Successfully tagged whale:latest
```
うまくできたようだ。イメージを確認する。

```bash:ターミナル
yamamo-to@jetson-nano:~/Documents/Docker/whalesay$  docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
whale               latest              d142ce68452a        5 seconds ago       39.2MB
alpine              latest              1a773c1b496c        4 weeks ago         5.29MB
docker/whalesay     latest              6b362a9f73eb        4 years ago         247MB
```

whaleもできている。では実行。

```
yamamo-to@jetson-nano:~/Documents/Docker/whalesay$ docker run --rm whale
 _ 
<   >
 - 
    \
     \
      \
                    ##         .
              ## ## ##        ==
           ## ## ## ## ##    ===
       /"""""""""""""""""\___/ ===
      {                       /  ===-
       \______ O           __/
         \    \         __/
          \____\_______/
```

おぉ、動くじゃないか！素晴らしい。

# コンテナに入る

よし、では/bin/shを起動してコンテナを操作してみよう。

```
yamamo-to@jetson-nano:~/Documents/Docker/whalesay$ docker run -it --rm whale /bin/sh
 _________ 
< /bin/sh >
 --------- 
    \
     \
      \
                    ##         .
              ## ## ##        ==
           ## ## ## ## ##    ===
       /"""""""""""""""""\___/ ===
      {                       /  ===-
       \______ O           __/
         \    \         __/
          \____\_______/
```

あぁ、お前はそういうヤツだったな・・・。DockerfileでENTRYPOINTが設定されていた。ENTRYPOINTをCMDに変更してリビルドする。

```bash:ターミナル
yamamo-to@jetson-nano:~/Documents/Docker/whalesay$ sed -i 's/ENTRYPOINT/CMD/' Dockerfile
yamamo-to@jetson-nano:~/Documents/Docker/whalesay$ docker build -t whale .
```

気を取り直して再度実行する。

```:ターミナル
yamamo-to@jetson-nano:~/Documents/Docker/whalesay$ docker run -it --rm whale /bin/sh
/ #
```
よし、コンテナに入れた。

# コンテナを調べる

まずはunameから。

```:Dockerコンテナ内
/ # uname -a
Linux e5952c9841fa 4.9.140-tegra #1 SMP PREEMPT Wed Mar 13 00:32:22 PDT 2019 aarch64 Linux
```

アーキテクチャは`aarch64`となっている。カーネルバージョンが`4.9.140-tegra`だ。これはJetPack 4.2と全く同じものである。/dev以下はどうかと言うと

```:Dockerコンテナ内
/ # ls /dev
console  fd       full     mqueue   null     ptmx     pts      
random   shm      stderr   stdin    stdout   tty      urandom  zero
```

うーん・・・。これではGPUと連動しなさそうだ。ちなみにJetson Nanoでは/dev以下にnvから始まるものだけでも23個のデバイスファイルがある。

```bash:ターミナル
yamamo-to@jetson-nano:~$ ls -l /dev/nv* 
crw-rw---- 1 root video 506,  1  6月  9 19:53 /dev/nvhost-as-gpu
crw-rw---- 1 root video 242,  0  6月  9 19:53 /dev/nvhost-ctrl
crw-rw---- 1 root video 506,  2  6月  9 19:53 /dev/nvhost-ctrl-gpu
crw-rw---- 1 root video 242, 26  6月  9 19:53 /dev/nvhost-ctrl-isp
crw-rw---- 1 root video 242, 30  6月  9 19:53 /dev/nvhost-ctrl-isp.1
crw-rw---- 1 root video 242, 10  6月  9 19:53 /dev/nvhost-ctrl-nvdec
crw-rw---- 1 root video 242, 34  6月  9 19:53 /dev/nvhost-ctrl-vi
crw-rw---- 1 root video 506,  6  6月  9 19:53 /dev/nvhost-ctxsw-gpu
crw-rw---- 1 root root  506,  3  6月  9 19:53 /dev/nvhost-dbg-gpu
crw-rw---- 1 root video 506,  0  6月  9 19:53 /dev/nvhost-gpu
crw-rw---- 1 root video 242, 25  6月  9 19:53 /dev/nvhost-isp
crw-rw---- 1 root video 242, 29  6月  9 19:53 /dev/nvhost-isp.1
crw-rw---- 1 root video 242, 17  6月  9 19:53 /dev/nvhost-msenc
crw-rw---- 1 root video 242,  9  6月  9 19:53 /dev/nvhost-nvdec
crw-rw---- 1 root video 242, 21  6月  9 19:53 /dev/nvhost-nvjpg
crw-rw---- 1 root root  506,  4  6月  9 19:53 /dev/nvhost-prof-gpu
crw-rw---- 1 root video 506,  7  6月  9 19:53 /dev/nvhost-sched-gpu
crw-rw---- 1 root video 242,  1  6月  9 19:53 /dev/nvhost-tsec
crw-rw---- 1 root video 242,  5  6月  9 19:53 /dev/nvhost-tsecb
crw-rw---- 1 root video 506,  5  6月  9 19:53 /dev/nvhost-tsg-gpu
crw-rw---- 1 root video 242, 33  6月  9 19:53 /dev/nvhost-vi
crw-rw---- 1 root video 242, 13  6月  9 19:53 /dev/nvhost-vic
crw-rw---- 1 root video  10, 61  6月  9 19:53 /dev/nvmap
```

コンテナ内の/devをホストの/devでマウントすれば連動するんだろうか・・・。とりあえずDockerのイメージはalpine linuxベースなのでlshwパッケージをインストールして認識されているデバイスを調べることにする。

まずはパッケージのインストール。

```:Dockerコンテナ内
/ # apk add lshw
```

普通にインストールできた。ではlshwの実行。

```:Dockerコンテナ内
/ # lshw
(途中省略)
          description: PCI bridge
          product: NVIDIA Corporation
          vendor: NVIDIA Corporation
          physical id: 2
          bus info: pci@0000:00:02.0
          version: a1
          width: 32 bits
          clock: 33MHz
          capabilities: pci normal_decode bus_master cap_list
          configuration: driver=pcieport
          resources: irq:84 ioport:1000(size=4096) memory:13000000-130fffff
```

お、正しくGPUが認識されている。内容は素のJetson Nanoと全く同じ。これはもしかしてGPUが動くのか?と期待しながら色々と模索しようと思う。