osrf/rockerを使ってPC内に複数のROS distroの開発環境を整える方法

Dockerを使ってGUIアプリケーションを起動するには、起動にちょっと工夫が必要だったり一筋縄では行かないことが多いです。
osrf/rockerというツールを使うと一筋縄では行かない部分を少しだけ簡単にできるので、その使い方を紹介します。

今回紹介する方法を確認したのはUbuntuのみ(Windows/macOSでは未確認)です。

動作するUbuntuのディストリビューションが異なるROSのディストリビューションを複数対象(Ubuntu 18.04+ROS MelodicとUbuntu 20.04+ROS Noeticなど)としてROSパッケージを開発したい。でもそのときにOSやPCは切り替えたくない。という状況を想定して紹介します。

この記事はROS Advent Calendar 2021の17日目として投稿しています。

目次

概要

Dockerを使ってGUIアプリケーションを起動する(X11を利用する)ためには、起動に-e DISPLAY=$DISPLAY-v /tmp/.X11-unix:/tmp/.X11-unixなどのオプションを指定したりする必要があります。SpritaroさんのQiitaの記事が詳しいです。

Qiita
DockerでGUIを表示するときの仕組みについて - Qiita はじめにDockerでGUIを表示したいとき、何が起きているのか理解したかったのでメモを作りました。参考にしたのはROSのチュートリアルですが、それ以外のコンテナでも同様だ...

さらにNVIDIAのGPUが搭載されている場合は--gpuオプションを指定したり、NVIDIA_VISIBLE_DEVICES変数を定義したりなどとにかく大変です。

これを「イイ感じ」に楽にしてくれるosrf/rockerというPython製のツールがあります。
README読んだだけでは実際の運用をイメージするのが難しいと思うので、この記事ではその使い方を紹介します。

GitHub
GitHub - osrf/rocker: A tool to run docker containers with overlays and convenient options for thing... A tool to run docker containers with overlays and convenient options for things like GUIs etc. - osrf/rocker

具体的にはUbuntuがインストールされたPCでROS MelodicとNoetic、ROS 2 FoxyとGalacticの合計4種類のROSディストリビューション向けのパッケージを開発・メンテナンスするという状況でOSやPCを切り替えずに済むような開発環境の構築方法とその使い方を紹介します。

X11(X Window System)とDockerについては以下の記事が参考になると思います。

Qiita
DockerでGUIを表示するときの仕組みについて - Qiita はじめにDockerでGUIを表示したいとき、何が起きているのか理解したかったのでメモを作りました。参考にしたのはROSのチュートリアルですが、それ以外のコンテナでも同様だ...

とりあえず動かしてみたいという方、macOSやWindowsでも試したいという方はWebブラウザ経由でアクセスできる方法ならより簡単に扱えると思います。

あわせて読みたい
ROS/ROS2のGUIをWebブラウザ経由でお手軽に試せるDockerfileを公開しました ROS/ROS 2のGUIをWebブラウザ経由でお手軽に試せるDockerfileとDockerイメージを公開しています。その特徴と使用方法を紹介します。 今回紹介するのは Ubuntu Desktop(...

動作環境

Ubuntuのみ(Windows/macOSでは未確認)です

今回使用した環境は以下の通りです。

  • CPU: Intel Core i5-9600K
  • GPU: NVIDIA GeForce RTX 2070 SUPER
  • OS: Ubuntu 18.04.5
  • Docker: 20.10.4 (build d3cb89e)
  • NVIDIA Driver: 460.39
  • nvidia-docker2: 2.6.0-1
  • osrf/rocker: v0.2.7

GPUのドライバやDockerのインストールについてはここでは詳細は省略します。

基本的には現時点ではDockerをインストールし、その後nvidia-docker2をインストールするのが良さそうです。
ややこしいのですが、ググって出てくる情報はnvidia-dockerコマンドのためのnvidia-docker2について(2019年以前の古い情報)とNVIDIA
Container Toolkitをインストールするためのnvidia-docker2について(2021年12月17日現在最新の情報)の情報が混じっています。

インストール方法についてはNVIDIA JapanのMediumが参考になると思います。

Medium
NVIDIA Docker って今どうなってるの? (20.09 版) ※ この記事は以前私が Qiita に書いたものを、現状に合わせて更新したものです。(内容、結構変わりました)

osrf/rockerについて

osrf/rockerはOpen Roboticsがメンテナンスしているツールです。
Dockerコンテナを起動する際にNVIDIAのGPUのサポートをしたり、ユーザを設定したりしてくれます。

※Dockerコンテナは基本的にrootユーザで起動することが多いので、コンテナ内で編集したファイルは所有者がrootになってしまって一般ユーザからファイルが扱いにくくなったりします。Dockerコンテナ起動時にユーザを適切に設定することで、ファイルのパーミッションや所有者の問題を回避できます。

GitHub
GitHub - osrf/rocker: A tool to run docker containers with overlays and convenient options for thing... A tool to run docker containers with overlays and convenient options for things like GUIs etc. - osrf/rocker

実はROS Japan UG #42 LT大会の「ROS+Docker環境構築手法n選」でちょっとだけ紹介していました。

ちなみにRの実行環境の「Rocker」も存在するそうです。ややこしい。

GitHub
GitHub - rocker-org/rocker: R configurations for Docker R configurations for Docker. Contribute to rocker-org/rocker development by creating an account on GitHub.

本記事では以後、単に「rocker」と書いた場合は「osrf/rocker」を指します。

rockerのインストール方法

rockerはAPTでインストールすることをおすすめします。

APTでROSをインストールできるようにsources.listを更新しておけば(apt installでROSをインストールできるようにしておけば)以下のコマンドでインストールできます。

sudo apt install python3-rocker

rockerの基本的な使い方

rockerの基本的な使い方は以下のコマンドになると思います。

NVIDIAのGPUありの場合

rocker --nvidia --x11 --user --home osrf/ros:noetic-desktop-full

NVIDIAのGPUなしの場合

rocker --x11 --user --home osrf/ros:noetic-desktop-full

このコマンドでUbuntu 18.04がインストールされたPCでもROS Noeticの環境を起動することができるようになります。
noeticmelodicに置き換えて実行すればROS Melodicの環境を起動することもできます。もちろんUbuntu 20.04がインストールされたPCでも使えます。

【2022年10月13日追記】
ROS 2用イメージの場合はタグの命名規則が異なるようです。
Foxyの場合はDockerイメージ名がosrf/ros:foxy-desktop となります。その他に使用できるタグ名についてはDocker Hubから確認できます。

https://hub.docker.com/r/osrf/ros/tags
https://hub.docker.com/_/ros/tags

Ubuntu18.04でROS Noeticが扱えるだけでもかなりありがたいのですが、このコマンドだけだと私の場合は以下のような不便さを感じることがありました。

  • ROSのワークスペースとしてよく使用する~/catkin_ws~/ros2_wsを都度ビルドしないといけないので大変
  • 必要なパッケージが入っていないので都度インストールするのが大変
  • インストールされているパッケージが使いたいバージョンと合わないので都度インストールするのが大変

これらの問題を解決するために、ワークスペースについてはディレクトリ構造を見直し、自分で使いたいDockerイメージを作ることにしました。

rockerで扱いやすいワークスペースの構成

ROSのワークスペース(よく使用するのは~/catkin_ws~/ros2_ws)は基本的にはディストリビューションごとに用意する必要があります。
ROS MelodicでビルドしたものをROS Noeticでそのままsource devel/setup.bashしても基本的にはうまく動かない場合が多いです。
よく使われる~/catkin_ws~/ros2_wsのままだとROS MelodicとROS Noeticでワークスペースを使いまわすことになり、都度devel/installbuildなどを削除してビルドし直さないといけないので大変です。

そこで以下のようなディレクトリ構成に変えました。

ros
├── dashing
│   ├── build
│   ├── install
│   ├── log
│   └── src
├── foxy
│   ├── build
│   ├── install
│   ├── log
│   └── src
├── galactic
│   ├── build
│   ├── install
│   ├── log
│   └── src
├── melodic
│   ├── build
│   ├── devel
│   ├── log
│   └── src
└── noetic
    ├── build
    ├── install
    ├── log
    └── src

この構成にすればrockerコマンドでDockerコンテナ起動後、以下のようにコマンドを実行すれば、roslaunch/ros2 launchが実行できます。

ROS Melodicの場合

cd ~/ros/melodic
# 必要に応じてcatkin build
source devel/setup.bash

ROS 2 Foxyの場合

cd ~/ros/foxy
# 必要に応じてcolcon build --symlink-install
source install/setup.bash

Dockerイメージについて

Open Roboticsがメンテンスしているosrf/rosのイメージは必要最小限の構成となっており、Gitやtmuxなどがインストールされていません。

GitHub
GitHub - osrf/docker_images: A repository to hold definitions of docker images maintained by OSRF A repository to hold definitions of docker images maintained by OSRF - osrf/docker_images

そこで、しばらく使ってみて必要そうだとわかったソフトウェアを大体インストールした構成のDockerfileを公開しました。

GitHub
GitHub - Tiryoh/docker-ros: Dockerfiles to use ROS with osrf/rocker Dockerfiles to use ROS with osrf/rocker. Contribute to Tiryoh/docker-ros development by creating an account on GitHub.
GitHub
GitHub - Tiryoh/docker-ros2: unofficial ROS 2 Dockerfile unofficial ROS 2 Dockerfile. Contribute to Tiryoh/docker-ros2 development by creating an account on GitHub.

Dockerfileの使い方

Dockerfileをダウンロードして編集し、ビルドする方法を紹介します。
今回はROS 2 Foxyのイメージに追加でros-foxy-turtlebot3をインストールしたい場合を例にします。

git cloneコマンドでダウンロードします。

git clone https://github.com/Tiryoh/docker-ros2.git

foxy/Dockerfileを編集します。

    apt-get install -y --no-install-recommends ros-${ROS_DISTRO}-gazebo-ros-pkgs ros-${ROS_DISTRO}-xacro ros-${ROS_DISTRO}-joint-state-publisher-gui && \
+   apt-get install -y --no-install-recommends ros-foxy-turtlebot3  && \
    rm -rf /var/lib/apt/lists/*

docker-ros2/foxyディレクトリでdocker buildを実行しDockerイメージを作成します。

docker build -t tiryoh/ros2:foxy .

先程のrockerコマンドでDockerコンテナを起動します。

rocker --nvidia --x11 --user --home tiryoh/ros2:foxy

Bashが起動します。

lsコマンドでホストマシンのファイルへアクセスできることも確認できます。

rviz2と入力して実行するとRViz2が起動します。

--nvidiaオプションをつけてrockerを実行した場合はGUIがGPUを利用できていることも確認できます。
rockerで起動したDockerコンテナ内でGazeboを起動し、ホストマシンでnvidia-smiを実行して確認しました。

実際の使い方案

「ROS Melodic/ROS Noetic/ROS 2 Foxy/ROS 2 Galactic向けにROSパッケージを開発したい」というような場面では、本記事内で紹介したrockerで扱いやすいワークスペースの構成に合わせてそれぞれに必要なパッケージを入れておき、rockerでDockerコンテナを起動してROSパッケージの動作確認をするような運用ができると思います。

複数のパッケージをgit cloneしてくるのは大変だと思うのでvcstoolを活用できるとよいと思います。

あわせて読みたい
ROSパッケージ管理に使うバージョン管理ツールの違いとその使い方 ROS/ROS2のパッケージ管理のためにバージョン管理について調べていると、vcstools, wstool, rosinstall, vcstoolなど様々なバージョン管理ツールやバージョン管理のため...

ROS Melodic用Dockerコンテナ起動

rocker --nvidia --x11 --user --home tiryoh/ros:melodic

ROS Noetic用Dockerコンテナ起動

rocker --nvidia --x11 --user --home tiryoh/ros:noetic

ROS 2 Foxy用Dockerコンテナ起動

rocker --nvidia --x11 --user --home tiryoh/ros2:foxy

ROS 2 Galactic用Dockerコンテナ起動

rocker --nvidia --x11 --user --home tiryoh/ros2:galactic

roslaunch実行後、rostopic listを実行するような場合には、すでに起動しているDockerコンテナに別の端末から接続するよりも、tmuxなどのターミナルマルチプレクサを活用する方が便利だと思います。

Qiita
アニメーションで学ぶtmux入門 ~精選10機能~ - Qiita はじめに本記事では tmux の使い方を学ぶために、コマンドとキーだけではなく GIF画像によるアニメーション を利用し、使い方をイメージしやすいようにしました。tmux とは...
MyEnigma
ターミナル生活を快適にするための端末多重化ソフトウェアtmux入門 - MyEnigma ターミナルマルチプレクサ tmux 入門posted with カエレバ戸田 薫 2012-12-30 Amazonで探す楽天市場で探すYahooショッピングで探す 目次 目次 はじめに インストール方法 M...

まとめ

rockerを使う環境を作成するまでの流れ、rockerの基本的な使い方を紹介しました。
さらにrockerを便利に扱う方法としてrockerで便利なROSワークスペースのディレクトリ構成例と、rockerから扱うのに便利なDockerイメージの作り方を紹介しました。

Dockerfile参考になったという方はぜひGitHubリポジトリにStarをつけていただけると励みになります!

GitHub
GitHub - Tiryoh/docker-ros: Dockerfiles to use ROS with osrf/rocker Dockerfiles to use ROS with osrf/rocker. Contribute to Tiryoh/docker-ros development by creating an account on GitHub.
GitHub
GitHub - Tiryoh/docker-ros2: unofficial ROS 2 Dockerfile unofficial ROS 2 Dockerfile. Contribute to Tiryoh/docker-ros2 development by creating an account on GitHub.

FAQ

apt updateをした場合のGPG keyのエラー

building > Reading package lists...
building > W: GPG error: http://packages.ros.org/ros2/ubuntu focal InRelease: The following signatures were invalid: EXPKEYSIG F42ED6FBAB17C654 Open Robotics <[email protected]>
E: The repository 'http://packages.ros.org/ros2/ubuntu focal InRelease' is not signed.

上記のようにエラーが出る場合はDockerイメージが古い可能性があります。
docker pull osrf/ros:noetic-desktop-fullなどで最新版をダウンロードしてみてください。

ネットワークを--network hostで指定した場合のエラー

一部のイメージでは--network hostを指定した場合にRViz等Qtを使うアプリケーションを起動できず、以下のように異常終了してしまう場合があります。

$ rviz
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-daisuke'
[ INFO] [1639679761.103031358]: rviz version 1.13.21
[ INFO] [1639679761.103057954]: compiled against Qt version 5.9.5
[ INFO] [1639679761.103064928]: compiled against OGRE version 1.9.0 (Ghadamon)
dbus[38]: The last reference on a connection was dropped without closing the connection. This is a bug in an application. See dbus_connection_unref() documentation for details.
Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.
  D-Bus not built with -rdynamic so unable to print a backtrace
Aborted (core dumped)

rockerコマンドに以下のように --privilegedオプションをつけるというのがひとまずの問題回避策のようです。

rocker --nvidia --x11 --user --network host --privileged --volume ~/ros2_ws/src ~/.bashrc -- tiryoh/ros2:foxy

ホストマシンの/var/log/syslogを確認すると以下のようなエラーが出ていました。

dbus-daemon: apparmor="DENIED" operation="dbus_method_call"  bus="accessibility" path="/org/freedesktop/DBus" interface="org.freedesktop.DBus" member="Hello" mask="send" name="org.freedesktop.DBus" pid=17471 label="docker-default" peer_label="unconfined"

これは既知の問題で、DockerのコアであるMobyでもIssueが作成されています。

GitHub
combination of qt gui apps + host network crashes · Issue #13 · osrf/rocker I'm putting this here for reference as it was one of the first things I tried to do with rviz2. It looks like there's an issue upstream about this: moby/moby#38...
GitHub
ubuntu:bionic image: GUIs and --network=host problems · Issue #3 · diegoferigo/development-iit Images based on ubuntu:bionic are affected by a regression caused by the interaction between host's and container's dbus. This happens only if --network host is...
GitHub
Qt applications and network host · Issue #38442 · moby/moby Description Qt applications like qtcreator do not work if the network mode is host unless the container is executed as privileged. It might be related to #36417...

参考

Qiita
osrf / rockerでROS/ROS2のためのGUIコンテナ環境構築 - Qiita はじめに本格的にROS2を使いたいと思っていた所、ROS Japan UG #42 LT大会の資料にずっとやりたかったGUIが使えるコンテナ環境構築のやり方があったので実際にやってみる。...

rockerのオプション

$ rocker --help
Extension volume doesn't support default arguments. Please extend it.
usage: rocker [-h] [--noexecute] [--nocache] [--nocleanup] [--pull] [-v]
              [--dev-helpers] [--devices [DEVICES [DEVICES ...]]]
              [--env NAME[=VALUE] [NAME[=VALUE] ...]] [--env-file ENV_FILE]
              [--git] [--git-config-path GIT_CONFIG_PATH] [--home]
              [--name NAME] [--network {host,none,bridge}] [--nvidia]
              [--privileged] [--pulse] [--ssh] [--user]
              [--user-override-name USER_OVERRIDE_NAME] [--user-preserve-home]
              [--volume HOST-DIR[:CONTAINER-DIR[:OPTIONS]]
              [HOST-DIR[:CONTAINER-DIR[:OPTIONS]] ...]] [--x11]
              [--mode {interactive,non-interactive,dry-run}]
              [--image-name IMAGE_NAME]
              [--extension-blacklist [EXTENSION_BLACKLIST [EXTENSION_BLACKLIST ...]]]
              image [command [command ...]]

A tool for running docker with extra options

positional arguments:
  image
  command

optional arguments:
  -h, --help            show this help message and exit
  --noexecute           Deprecated (default: False)
  --nocache
  --nocleanup           do not remove the docker container when stopped
                        (default: False)
  --pull
  -v, --version         show program's version number and exit
  --dev-helpers         add development tools emacs and byobu to your
                        environment (default: None)
  --devices [DEVICES [DEVICES ...]]
                        Mount devices into the container. (default: None)
  --env NAME[=VALUE] [NAME[=VALUE] ...], -e NAME[=VALUE] [NAME[=VALUE] ...]
                        set environment variables (default: [])
  --env-file ENV_FILE   set environment variable via env-file (default: None)
  --git                 Use the global Git settings from the host
                        (/etc/gitconfig and ~/.gitconfig) (default: None)
  --git-config-path GIT_CONFIG_PATH
                        Override the path to the git config default:
                        /home/daisuke/.gitconfig (default:
                        /home/daisuke/.gitconfig)
  --home                mount the users home directory (default: None)
  --name NAME           Name of the container. (default: )
  --network {host,none,bridge}
                        What network configuration to use. (default: None)
  --nvidia              Enable nvidia (default: None)
  --privileged          give extended privileges to the container (default:
                        None)
  --pulse               mount pulse audio devices (default: None)
  --ssh                 Forward SSH agent into the container (default: None)
  --user                mount the current user's id and run as that user
                        (default: None)
  --user-override-name USER_OVERRIDE_NAME
                        override the current user's name (default: None)
  --user-preserve-home  Do not delete home directory if it exists when making
                        a new user. (default: False)
  --volume HOST-DIR[:CONTAINER-DIR[:OPTIONS]] [HOST-DIR[:CONTAINER-DIR[:OPTIONS]] ...]
                        volume volumes in container (default: None)
  --x11                 Enable x11 (default: None)
  --mode {interactive,non-interactive,dry-run}
                        Choose mode of operation for rocker (default:
                        interactive)
  --image-name IMAGE_NAME
                        Tag the final image, useful with dry-run (default:
                        None)
  --extension-blacklist [EXTENSION_BLACKLIST [EXTENSION_BLACKLIST ...]]
                        Prevent any of these extensions from being loaded.
                        (default: [])

更新履歴

2022年10月13日

rockerの基本的な使い方で指定するDockerイメージのタグ名について追記

2022年10月24日

DockerでGUIを表示するときの仕組みについて、Spritaroさんの記事へのリンクを追加

この記事が気に入ったら
フォローしてね!

よかったらシェアしていただけると励みになります!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

Memotekiの管理人です。このブログには学んだことや共有しておきたいことをマイペースにメモしていきます。2020年からは日記も書き始めました。

コメント

コメントする


reCaptcha の認証期間が終了しました。ページを再読み込みしてください。

目次