Docker＋ROSの環境をWindows10PROで整える

#書いた理由
Docker+ROSで開発する人は多くいて、懇切丁寧なチュートリアルがDockerHubのROSのリポジトリにも書いてありますが、私のようにまったくDocker使ったことない人には、Dockerの使い方やコマンドからメモっておかないと使えません（泣）
3日経ったらやり方を忘れてしまうと思って備忘録代わりに書いておきます。

#環境
Windows10Pro
HomeエディションではHyperVを使用できなかったため、アップグレードして使用しました。

#想定する使い方
WindowsのDockerコンテナにハードウェアをマウントすることは2020/01/26現在は無理のようです。
WindowsPCとJetson-nanoを無線LANでつなぎ、ハードウェアの集まるJetson-nanoとROSでデータを交換しながら開発する。
最終的にはJetson-nano単独で動かしますが、開発だけでも大きなPCでできれば楽ができます。

#Docker+ROSの環境で開発したい

Jetson-nanoにつないだ小さなディスプレイで開発するのが大変になってきたので、Windows10をProにアップグレードしてDocker DeskTopを使うことにしました。
DonkeyCar用にAnacondaの環境が入っているので、競合を回避するのが目的です。
また、DockerHubのリポジトリを持ってくることで環境構築の負担を減らすのが目的です。
もともと仮想マシンでUbuntuを入れてみましたが、うまく動かないのでDockerに宗旨替えしました。

##Docker Desktopのインストール
[https://www.docker.com/products/docker-desktop](https://www.docker.com/products/docker-desktop)
公式のマニュアルに沿ってインストールします。
Windows10Proじゃないと、HyperVが動かないので使えません。
HyperVを有効にして再起動したらあっさり動きました。
GUIでDockerHubのユーザーIDとかを設定しておきます。

##ROSのイメージをPULLしてみる

適当なディレクトリを作って、コマンドを開いて、
`docker pull ros`
これでDockerHubからROSのリポジトリを引っ張れました。
バージョンを指定するときは、
`docker pull ros:melodic`
とかするとOK。

##ROSのイメージの中で作業する
`docker run -it --name test ros`
pullしたコンテナイメージを動かし、コンテナの中で作業できます。

`-it`  コンテナのSTDINにアタッチし疑似ターミナルを割り当て
`-name` ホスト名を決めてコンテナ起動

##ROSコンテナにtoolをインストール
catkin buildが動かないので、ツールは公式イメージに入っていないらしいです。
コンテナの中でツールをインストールします。
`sudo apt install python-catkin-tools`
では何故かインストールできなかったので、apt-getを使いました。

```bash:ROS
sudo apt-get update
sudo apt-get install python-catkin-tools
```

で、セットアップ完了。

```bash:ROS
mkdir -p catkin_ws/src/
cd ..
catkin build
```

これでパッケージのビルドができるようになりました。

`exit` で抜けることができます。抜けてもコンテナは動作している状態です。
再度、開始とアタッチをするなら

```bash:command
docker start test
docker attach test
```

##コンテナイメージのバックアップ
exitした後、タグをつけてイメージを保存します。

```bash:command
docker commit test ros:ros-test
```

このタグを使って新しいイメージを起動します。名前は先ほど使ったtestを使うとコンテナ名が重複するのでNG。

```bash:command
docker run -it --name build ros:ros-test
```

##DockerHubにリポジトリを登録する
DockerHubに保存するため、新しいリポジトリを作成します。
`docker commit build tkumazawa/ros:build` と打ち込んで実行し、イメージを確認します。
tkumazawaは私のDocker HubのIDです。rosがリポジトリ名。buildがタグです。タグはver1.0などとしたほうがいいかもしれません。

```bash:command
> docker commit build tkumazawa/ros:build
> docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
tkumazawa/ros       build               2ff967da7a65        30 seconds ago      1.28GB
ros                 ros-build           2edba62b8053        22 hours ago        1.28GB
```

整ったらDockerHubにPUSHします。


```bash:command
>docker push tkumazawa/ros
The push refers to repository [docker.io/tkumazawa/ros]
8493815d0ca4: Pushed
372ede2259c3: Pushed
9e4af5cbf92b: Pushed
5d0ac2ca4dca: Mounted from library/ros
b0264d2ecd66: Mounted from library/ros
dc1e02c4e5b2: Mounted from library/ros
93928f93457b: Mounted from library/ros
95c9f2e4b310: Mounted from library/ros
5dfc22a79953: Mounted from library/ros
deb603bf064b: Mounted from library/ros
f5a315154171: Mounted from library/ros
55388b609b06: Mounted from library/ros
f55aa0bd26b8: Mounted from library/ros
1d0dfb259f6a: Mounted from library/ros
21ec61b65b20: Mounted from library/ros
43c67172d1d1: Mounted from library/ros
build: digest:
```

これでDockerで整えた環境をDockerHubに保存してバックアップすることができます。

実際にDocker+ROSで動かす方法はここを参考にしました。
[Docker + ROS(kinetic)でチュートリアル](https://qiita.com/Leonardo-mbc/items/cfd38a4fae8667593cf1)

##コンテナの削除がめんどくさい
やっているうちに大量のコンテナとイメージがメモリを圧迫しています。
ROSのコンテナが複数起動しているので、どうにもなりません。
で、「Docker実践入門」という本を教科書にしてますが、bashだと
`docker rm $(docker ps -qa)`で済むんですよね？
Windowsで同じことやろうとしたら、

```bash:command
#停止中コンテナの全消去
for /f "usebackq" %x in (`docker ps -aq`) do docker rm %x
#起動中コンテナも停止中コンテナも全消去
for /f "usebackq" %x in (`docker ps -aq`) do docker rm -f %x
#未参照のイメージを全消去
for /f "usebackq" %x in (`docker images -q`) do docker rmi %x
```

参考にしたのはこちら。
[WindowsのDockerで溜まったコンテナやイメージを削除する](https://qiita.com/akima/items/29e4c8905ec8d9ec08ff)

コンテナを消し終わったら、タグ付きでコミットしたイメージを消去。
怖いので一個ずつ消す。
`docker rmi ros:ros-test`
これやったら根っこから全部消える。もう一回、DockerHubからとってくるならOK。
`docker rmi ros`

##VSCodeでDockerコンテナにリモート接続する
編集するときにいちいちエディタをコンテナにインストールするのが面倒だと思っていたらVSCodeにRemote Containersなる拡張を発見。
[microsoft/vscode-remote-release](https://github.com/Microsoft/vscode-remote-release)

インストールして左下の隅っこをクリックするとメニューが開くので、`Remote-Containers: Attach to running Container` で接続したい対象を選択できます。
まず、先ほどDockerHubにpushしたイメージからコンテナを起動します。
`docker run -it --name ros-wk tkumazawa/ros`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328520/96dccb70-8ff3-9fa2-d6af-e8d7875c0a35.png)

先ほど立ち上げたros-wkを選択すると、新しいVSCodeのウィンドウが立ち上がるので、フォルダを選択して起動。
確かに中身が見えます。

##GitHubからコンテナの中にリポジトリをcloneする
githubから編集中の自分のROSのパッケージをcloneします。
`https://github.com/kumaxxp/ros_rc_package.git`
これで、コンテナの中にgithubの内容を取り込んで編集できそうです。
ただし、GitHistoryやGitLensは無効で動きませんでした。なにか制限がかかっているようです。
VSCode標準のgit機能は問題なく使えます。githubへのpushもできますが、いちいちパスワードとIDを打ち込むのは面倒ですね。
かといってしょっちゅう生成と削除を繰り返す前提のコンテナイメージのssh-keyを登録するのもどうかと思いますので、その辺りは悩ましいところです。
とりあえず`catkin build`してみます。

```bash:ROS
# catkin build
----------------------------------------------------
Profile:                     default
Extending:             [env] /opt/ros/melodic
Workspace:                   /root/catkin_ws
----------------------------------------------------
Build Space:        [exists] /root/catkin_ws/build
Devel Space:        [exists] /root/catkin_ws/devel
Install Space:      [unused] /root/catkin_ws/install
Log Space:          [exists] /root/catkin_ws/logs
Source Space:       [exists] /root/catkin_ws/src
DESTDIR:            [unused] None
----------------------------------------------------
Devel Space Layout:          linked
Install Space Layout:        None
----------------------------------------------------
Additional CMake Args:       None
Additional Make Args:        None
Additional catkin Make Args: None
Internal Make Job Server:    True
Cache Job Environments:      False
----------------------------------------------------
Whitelisted Packages:        None
Blacklisted Packages:        None
----------------------------------------------------
Workspace configuration appears valid.
----------------------------------------------------
[build] Found '1' packages in 0.0 seconds.
[build] Updating package table.
Starting  >>> ros_rc_package
Finished  <<< ros_rc_package                [ 4.5 seconds ]
[build] Summary: All 1 packages succeeded!
[build]   Ignored:   None.
[build]   Warnings:  None.
[build]   Abandoned: None.
[build]   Failed:    None.
[build] Runtime: 4.5 seconds total.
[build] Note: Workspace packages have changed, please re-source setup files to use them.
```
とりあえず、パッケージは問題なくbuildできたみたいです。
（**pythonで記述したものは実行するとエラーが確実に出るのでここでは動かせない**）

```bash:ROS
# . ~/catkin_ws/devel/setup.bash
# rospack list
...
ros_rc_package /root/catkin_ws/src/ros_rc_package
...
```
setupの後、パッケージのリストを出力させると、パッケージは登録されていました。

###続くかも
Dockerを使った機能の作成方法を、全部メモしてみました。
記述したコマンドをアレンジして使えば、とりあえずWindowsでDocker+ROS開発は問題なく実施できるかと思われます。