Docker: ROS1-noeticの環境イメージ作成(Ubuntu・Windows)


Docker: ROS1-noeticの環境イメージ作成

はじめに

Dockerのイメージ作成の練習として,
Ubuntu20.04上にROSを構築して,ワークスペース作成までのDockerイメージを作成してみる.

流れは以下のとおりである.

  1. Ubuntu20.04のイメージをベース
  2. ROSのインストールコマンドをDockerfile内で
  3. ワークスペースをDockerfile内で作成

注意したいところは,上記のものだけを適用しても,RvizなどのGUIは動かないこと.

前回の記事を参考にそのGUIも使えるようにしたROS環境の構築について詳しくまとめる.
また,ホストOSがUbuntuかWindowsかによって少し手順やDockerfileも異なるため,分けて記述する.

Ubuntu上での構築

Dockerfile
# osrfが提供するrosイメージ(タグがnoetic-desktop-full)をベースとしてダウンロード
FROM osrf/ros:noetic-desktop-full

# Docker実行してシェルに入ったときの初期ディレクトリ(ワークディレクトリ)の設定
WORKDIR /root/

# nvidia-container-runtime(描画するための環境変数の設定)
ENV NVIDIA_VISIBLE_DEVICES \
    ${NVIDIA_VISIBLE_DEVICES:-all}
ENV NVIDIA_DRIVER_CAPABILITIES \
    ${NVIDIA_DRIVER_CAPABILITIES:+$NVIDIA_DRIVER_CAPABILITIES,}graphics

# ROSの環境整理
# ROSのセットアップシェルスクリプトを.bashrcファイルに追記
RUN echo "source /opt/ros/noetic/setup.sh" >> .bashrc
# 自分のワークスペース作成のためにフォルダを作成
RUN mkdir -p catkin_ws/src
# srcディレクトリまで移動して,catkin_init_workspaceを実行.
# ただし,Dockerfileでは,.bashrcに追記した分はRUNごとに反映されないため,
# source /opt/ros/noetic/setup.shを実行しておかないと,catkin_init_workspaceを実行できない
RUN cd catkin_ws/src && . /opt/ros/noetic/setup.sh && catkin_init_workspace
# ~/に移動してから,catkin_wsディレクトリに移動して,上と同様にしてcatkin_makeを実行.
RUN cd && cd catkin_ws && . /opt/ros/noetic/setup.sh && catkin_make
# 自分のワークスペースが反映されるように,.bashrcファイルに追記.
RUN echo "source ./catkin_ws/devel/setup.bash" >> .bashrc

1行ずつ何をしているかについては,コメントアウトで示すとおりである.

GUI有効にするための工夫

run.sh
# If not working, first do: sudo rm -rf /tmp/.docker.xauth
# It still not working, try running the script as root.
	
xhost +
XAUTH=/tmp/.docker.xauth
if [ ! -f $XAUTH ]
then
    xauth_list=$(xauth nlist :0 | sed -e 's/^..../ffff/')
    if [ ! -z "$xauth_list" ]
    then
        echo $xauth_list | xauth -f $XAUTH nmerge -
    else
        touch $XAUTH
    fi
    chmod a+r $XAUTH
fi

docker run -it \
    --env="DISPLAY=$DISPLAY" \
    --env="QT_X11_NO_MITSHM=1" \
    --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
    --env="XAUTHORITY=$XAUTH" \
    --volume="$XAUTH:$XAUTH" \
    --runtime=nvidia \
    --name=ros1_noetic \
    ros1_noetic \
    bash
echo "done"

run.shの中にdocker runを含めているため,以下のようにするだけでよい.
肝としては,xhost +により,xserverへのアクセス権限を解放している.そのため,使用後には,xhost -にして,もとに戻すのが良いと思われる.docker側からもxserverにアクセスすべく,xserver に関わるx11についてマウントし,XAUTHについてもマウントしていることが分かる.

docker run
bash run.sh

Windows上での構築

Dockerfile
FROM osrf/ros:noetic-desktop-full

WORKDIR /root/

# xserverへアクセスする際の環境変数の設定
ENV DISPLAY host.docker.internal:0.0

# apt-getのアップデートとアップグレード
RUN apt-get update -y && apt-get upgrade -y
# x11-apps(xserverにアクセスするために必要なパッケージ)をインストール
RUN apt-get install x11-apps -y
RUN echo "source /opt/ros/noetic/setup.sh" >> .bashrc
RUN mkdir -p catkin_ws/src
RUN cd catkin_ws/src && . /opt/ros/noetic/setup.sh && catkin_init_workspace
RUN cd && cd catkin_ws && . /opt/ros/noetic/setup.sh && catkin_make
RUN echo "source ./catkin_ws/devel/setup.bash" >> .bashrc

Ubuntu側で説明した部分は説明を省いている.Widnwos側で追記した部分についてはコメントアウトで説明している.

docker run
docker run -it -v ${path}/share:/root/docker_share --name ros1_noetic ros1_noetic:latest /bin/bash

私の環境では,このように実行している.-v ${path}/share:/root/docker_shareにより,Dockerfileと同じディレクトリにあるshareフォルダをマウントすることで,dockerとホスト間でファイルのやり取りを可能にしている.これはdocker内で,docker_shareというディレクトリにつなげているが,もちろん,ROSのワークスペースと直接つないでもよいと考える.

おまけ(Makefileの利用)

最後にDockerを使う中で,非常にMakefileの便利さに気づかされたため,一例を示す.

まず,フォルダの配置.

フォルダの配置
docker_ros1_noetic_on_windows
  |- share
     |- README.md
  |- Dockerfile
  |- Makefile
  |- README.md
Makefile
path=D:/Docker/docker_ros1_noetic_on_windows

build:
	docker build -t ros1_noetic:latest .
run:
	docker run -it -v ${path}/share:/root/docker_share --name ros1_noetic ros1_noetic:latest /bin/bash
start:
	docker start ros1_noetic
shell:
	docker exec -it ros1_noetic bash
stop:
	docker stop ros1_noetic
rm:
	docker rm ros1_noetic
git:
	git add ./share/README.md
	git add ./Dockerfile
	git add ./Makefile
	git add ./README.md
	git commit -m "modified"
	git push -u origin main

このように,Makefileをつくれば,makeコマンドだけで,すべて扱えるようになる.

  • コンテナのイメージファイル作成
make build
  • コンテナ生成+起動
make run
  • コンテナ起動(コンテナ停止しているものを起動)
make start

※make runではすでにあるコンテナは起動できない

  • コンテナに入る(インタラクティブシェル)
make shell
  • コンテナ停止(停止しないと削除できない)
make stop
  • コンテナ削除
make rm
  • githubへプッシュ
make git

私の場合は,まだDocker Hubを活用できていないため,gitへのプッシュのみとしている.

感想

Ubuntu上での環境構築は比較的簡単だったが,Rvizの動作確認まで含めると,xhost +による解決を見つけるまでには少し時間がかかった.Windowsについても同様にできるかなと思ってやってみたら,そもそもxhost +とは何かというような形でエラー.xserverへの知識がゼロだったために,それを準備してあげることにも気づかず,丸1日2日ほど,時間を費やしてしまった.なんとかできたため良いとする.Dockerを学んでいく中で,Dockerが使えるようになっていくのは当たり前だが,Makefileやシェルスクリプトのありがたみを改めて知り,これは使っていかなければと思えたのは非常に大きい.これからも,理解を深めて活用していきたいと思う.ちなみに,すでにROS2(foxy)やPyTorchに関しても同様に,環境構築ができているが,共有する余裕があるかは分からない.できるだけ早めにまとめてはおきたいと考えてはいる.