Dockerでubuntuを動かす～インストールからROSにおける通信まで～

Windows，Macの方はDockerのインストールに[こちら](https://www.sejuku.net/blog/82240)の記事がおすすめです．

# 実行環境
　他のubuntuバージョンでも同様に行うことができると思いますが，私が実行した環境を一応示しておきます．

|OS|
|:----:|
|ubuntu20.04 LTS|


# Dockerのインストール

![docker.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727132/43a2fb05-f7cc-bc69-037c-465cacc90fe3.png)


### 1. Dockerリポジトリの設定
　[こちら](https://sid-fm.com/support/vm/guide/install-docker-ubuntu.html)の記事を参考にしました．

①　パケージの更新
```
$ sudo apt update
```
②　必要なパッケージをインストール
```
$ sudo apt install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common
```
③　Dockerの公式のGPG公開鍵のインストール
```
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
```

④　fingerprint 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88であることを確認
```
$ sudo apt-key fingerprint 0EBFCD88
```
【以下のように表示されればOK!】

```
pub  rsa4096 2017-02-22 [SCEA]
     9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88
uid          [ unknown] Docker Release (CE deb) 
sub  rsa4096 2017-02-22 [S]
```
⑤　リポジトリの追加
```
$ sudo add-apt-repository \
    "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
    $(lsb_release -cs) \
    stable"
```
### 2. DockerをInstall

①　パケージの更新
```
$ sudo apt update
```
②　最新版をインストール
```
$ sudo apt-get install docker-ce docker-ce-cli containerd.io
```


※　Dockerのコンテナ内はすでに管理者権限が有効なため"sudo"をつける必要はない．

# Docker image のプル

Docker Hubから使用したいイメージをプルする．

##### ・ubuntu18.04をプルしたいとき
```
$ docker pull ubuntu:18.04
```

##### ・rosが入ったubuntuをプルしたいとき(以下，ROS1のnoeticをプルする場合)
```
$ docker pull ros:noetic 
```

##### ・それぞれのコンテナ間，あるいはコンテナ-ホストLinux間通信したいとき(以下，ROS1のnoeticをプルする場合)
```
$ docker pull osrf/ros:noetic-desktop-full
```



# 実際に使用するとき

##### ・新しくコンテナを起動
```
$ docker run -it -d --name my-ubuntu ubuntu:18.04
```
##### ・現在起動中のコンテナを確認
```
$ docker ps
```
【以下のように表示されればOK!】
```
CONTAINER ID   IMAGE          COMMAND                  CREATED        STATUS        PORTS     NAMES
3f83be3f40a6   ros:melodic    "/ros_entrypoint.sh …"   21 hours ago   Up 21 hours             ros_melodic

```


##### ・コンテナに入る
```
$ docker exec -it my-ubuntu /bin/bash
```
【以下のように表示されればOK!】
```
root@ ~#
```
##### ・コンテナを出る
```
$ exit
```
##### ・コンテナを止める
```
$ docker stop my-ubuntu
```
##### ・コンテナを再起動
```
$ docker start my-ubuntu
```

# コンテナ-ホスト間でROSの通信を行う場合
※　以下はホストに"ROS noetic"，コンテナに"ROS melodic"を用いています．

![Screenshot from 2022-09-27 18-18-34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727132/d0981e5b-d925-a2c9-eff0-64bf151fba7d.png)
https://roboticseabass.com/2021/04/21/docker-and-ros/ より参照．


#### Host LinuxにROSをインストール
ホスト環境にROS環境がない場合は，以下のコマンドを実行してインストールしてください．
ここでは，ROSに関するinstall等の詳細な情報は割愛させていただきます．詳しいことを知りたい方は[公式HP](http://wiki.ros.org/ja/noetic/Installation/Ubuntu)を参照してください．
```
$ sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
$ sudo apt install curl
$ curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add -
$ sudo apt update
$ sudo apt install ros-noetic-desktop-full
```


## 例①　メッセージのやり取り
### Ⅰ. コンテナ → ホストの通信

|publisher|subscliber|
|:----:|:----:|
|Docker コンテナ|Host Linux|

### 【Host Linux側で行うこと】

ー－ー[ターミナル1]ー－－
①　以下のsourceコマンドを実行．
```
$ source /opt/ros/noetic/setup.bash
```
②　roscoreの起動．
```
$ roscore
```


### 【Docker コンテナ内で行うこと】
ー－－[ターミナル2]ー－－
①　Docker image をプル．
```
$ docker pull osrf/ros:melodic-desktop-full
```

②　コンテナの起動（以下ではコンテナの名前を"melodic"としています．）
```
$ docker run -it --net=host --name melodic osrf/ros:melodic-desktop-full
$ docker start melodic
```
③　現在起動中のコンテナの確認
```
$ docker ps
```
【以下のように表示されればOK!】
```
CONTAINER ID   IMAGE                           COMMAND                  CREATED         STATUS          PORTS     NAMES
1bc4e60a8159   osrf/ros:melodic-desktop-full   "/ros_entrypoint.sh …"   9 minutes ago   Up 8 minutes              melodic

```


③　コンテナに入る．
```
$ docker exec -it melodic bash
```
④　以下のsourceコマンドを実行．
```
$ source /opt/ros/melodic/setup.bash
```

※　毎回記入するのは大変なので，".bashrc"に記入し、起動時コマンドを実行する手間を省く。
　以下のコマンドで実行．（ホストLinux側でも同様に.bashrcに記入することは可能であるが，複数ディストリビューションを記入するとエラーが出るので，複数のディストリビューションを使い分けている方は毎回sourceすることをお勧めします．）
```
$ echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrc
$ source ~/.bashrc
```
④　publisherの起動（「1秒当たり10回"Hello"というメッセージを送る」という意味になる．）
```
$ rostopic pub -r 10 /chatter std_msgs/String "Hello"
```

* コンテナから出たいときなどに関するコマンドは[こちら](#実際に使用するとき)を参照．


### 【Host Linux側で行うこと】

ー－－[ターミナル3]ー－－
①　以下のsourceコマンドを実行．
```
$ source /opt/ros/noetic/setup.bash
```
②　rostopicが届いているかの確認
```
$ rostopic list
```
【以下のように表示されればOK!】
```
/chatter
/rosout
/rosout_agg
```

③　subscliberの起動
```
$ rostopic echo /chatter
```
【以下のように表示されれば通信の成功！】
```
data: "Hello"
---
data: "Hello"
---
data: "Hello"
---
```

### Ⅱ. コンテナ → ホストの通信

|publisher|subscliber|
|:----:|:----:|
|Host Linux|Docker コンテナ|

### 【Host Linux側で行うこと】

ー－ー[ターミナル1]ー－－
①　以下のsourceコマンドを実行．
```
$ source /opt/ros/noetic/setup.bash
```
②　roscoreの起動．
```
$ roscore
```
ー－－[ターミナル2]ー－－
①　以下のsourceコマンドを実行．
```
$ source /opt/ros/noetic/setup.bash
```
②　publisherの起動（「1秒当たり10回"Hello"というメッセージを送る」という意味になる．）
```
$ rostopic pub -r 10 /chatter std_msgs/String "Hello"
```

* コンテナから出たいときなどに関するコマンドは[こちら](#実際に使用するとき)を参照．



### 【Docker コンテナ内で行うこと】
ー－－[ターミナル2]ー－－
①　現在起動中のコンテナの確認
```
$ docker ps
```
【以下のように表示されればOK!】
```
CONTAINER ID   IMAGE                           COMMAND                  CREATED         STATUS          PORTS     NAMES
1bc4e60a8159   osrf/ros:melodic-desktop-full   "/ros_entrypoint.sh …"   9 minutes ago   Up 8 minutes              melodic

```

②　コンテナに入る．
```
$ docker exec -it melodic bash
```
③　以下のsourceコマンドを実行．
```
$ source /opt/ros/melodic/setup.bash
```
④　rostopicが届いているかの確認
```
$ rostopic list
```
【以下のように表示されればOK!】
```
/chatter
/rosout
/rosout_agg
```

⑤　subscliberの起動
```
$ rostopic echo /chatter
```
【以下のように表示されれば通信の成功！】
```
data: "Hello"
---
data: "Hello"
---
data: "Hello"
---
```


## 例②　turtlesimを用いる
### コンテナ → ホストの通信

|publisher|subscliber|
|:----:|:----:|
|Docker コンテナ|Host Linux|

### 【Host Linux側で行うこと】

ー－ー[ターミナル1]ー－－

①　以下のsourceコマンドを実行．
```
$ source /opt/ros/noetic/setup.bash
```
②　roscoreの起動．
```
$ roscore
```
ーーー[ターミナル2]ーーー
① turtlesim packageのインストール
```
$ sudo apt-get install ros-noetic-tutorials
```
②　以下のsourceコマンドを実行．
```
$ source /opt/ros/noetic/setup.bash
```
③ turtlesim の起動
```
$ rosrun turtlesim turtlesim_node
```



### 【Docker コンテナ内で行うこと】
ー－－[ターミナル3]ー－－
①　現在起動中のコンテナの確認
```
$ docker ps
```
【以下のように表示されればOK!】
```
CONTAINER ID   IMAGE                           COMMAND                  CREATED         STATUS          PORTS     NAMES
1bc4e60a8159   osrf/ros:melodic-desktop-full   "/ros_entrypoint.sh …"   9 minutes ago   Up 8 minutes              melodic

```
②　コンテナに入る．
```
$ docker exec -it melodic bash
```
③　以下のsourceコマンドを実行．
```
$ source /opt/ros/melodic/setup.bash
```


④　turtlesim packageのインストール
```
$ apt-get install ros-melodic-tutorials
```

⑤　turtleをキーボードを使って動かす．
```
$ rosrun turtlesim turtle_teleop_key
```

* コンテナから出たいときなどに関するコマンドは[こちら](#実際に使用するとき)を参照．


### 【Host Linux側で行うこと】

ー－－[ターミナル4]ー－－

①　以下のsourceコマンドを実行．
```
$ source /opt/ros/noetic/setup.bash
```
②　rostopicが届いているかの確認
```
$ rostopic list
```
【以下のように表示されればOK!】
```
/rosout
/rosout_agg
/turtle1/cmd_vel
/turtle1/color_sensor
/turtle1/pose
```

③　subscliberの起動
```
$ rostopic echo /turtle1/cmd_vel
```
【Dockerコンテナ内のターミナルでキーボードの矢印ボタンを押した際に、亀の動きに合わせて、以下のように表示されれば通信の成功！】
```
linear:
  x: 2.0
  y: 0.0
  z: 0.0
angular:
  x: 0.0
  y: 0.0
  z: 0.0
  ---
```




# 参考文献
・[【Linux入門】DockerでUbuntu18.04を構築する方法](https://www.sejuku.net/blog/82240)
・[Ubuntu 18.04 LTS / 20.04 LTS に Docker をインストールする](https://sid-fm.com/support/vm/guide/install-docker-ubuntu.html)
・[A Guide to Docker and ROS](https://roboticseabass.com/2021/04/21/docker-and-ros/)
・[ROS Noetic のUbuntu へのインストール](http://wiki.ros.org/ja/noetic/Installation/Ubuntu)