gggggraziegrazie

graizegrazieさんのやったこと、学んだことを記録する雑記帳です

ホストとコンテナでUbuntuバージョンが異なる場合にコンテナ上でCUDAを使えるようにする方法

はじめに

筆者の環境

  • ホストOS Ubuntu 24.05
  • コンテナOS Ubuntu 20.04
  • ROS on コンテナ ROS1 noetic

設定方針

  • コンテナのベースイメージは、nvidiaが提供するnvidia/cuda系のイメージを使う
    • UbuntuやOSRFが提供するイメージを使うと、ホスト
  • nvidia driverはホストのみにインストールし、コンテナにはインストールしない。
    • コンテナはホストのドライバーを使うようにする(共有する)

ホストの設定

コンテナの設定

Appendix:nvidia container toolkit

nvidiaが提供する、コンテナ上でGPUを使う/使った開発を行うためのツール。

  • nvidia container toolkitのレポジトリ

github.com

  • nvidia container toolkitのインストール&設定手順

docs.nvidia.com

Appendix:nvidia docker

元々はnvidia container toolkitではなく、nvidia dockerというツールを使っていた。しかし2024年1月にgithubのレポジトリがアーカイブ化され、nvidia container toolkitがメインなった。
github.com

自己レポジトリにおける外部レポジトリの管理

ソフトウェア開発を行う時、すべてを自分で開発するのは非効率的です。まして大規模ソフトウェア開発を行う場合、全てを自分で開発するのは現実的ではありません。そこでOSSなどを活用する訳ですが、これまでは自己流で管理していました。本記事では、1つのレポジトリでどのように外部レポジトリを管理するとよいのか調べた結果をまとめてみます。

まとめ

端的に言えば下記のようになります。

  • 自己レポジトリ内にlibsやsubmodulesなどの、外部レポジトリをまとめるためのディレクトリを作成し、外部レポジトリはそこに集約する
  • 外部レポジトリに変更を加える場合は、外部レポジトリをforkし、そこに変更を加えて管理する
  • git addするときに使いたい各外部レポジトリのバージョン・タグをclone / checkoutしておくと、git clone --recurse-submodulesしたときに自動的にそのリビジョンが取得される
  • バージョンを明示的に知らせたい、頻繁に更新したい場合は、READMEにバージョン・タグを記載し、手動で取得してもらうとよさそう(私見

submoduleの追加・管理の方法

1. git submodule add "URL" "path"
URLは、submoduleとして追加したいレポジトリの場所です。pathは、ローカルマシン上でレポジトリを配置するディレクトのパスを意味します。

2. (スキップ可能)使いたいブランチやタグを取得する
1だけだとHEADがを取得してしまうので、

git branch -b

か、

git fetch --tags | git checkout -b タグ名

を行い、必要なブランチかリビジョンを取得する。

注意点

  • submoduleは、外部のレポジトリを参照しているだけに過ぎないため、submoduleを変更してコミットしようとすると、作成した自己レポジトリではなく、外部レポジトリにコミットしてしまう点に注意。そのため変更する場合は、元の外部レポジトリからforkし、そこにコミットするようにする必要がある。または別ブランチにコミットすることも考えられる。

ros1_bridgeをDockerコンテナで使いたい

公式なdocker imageが提供されていました。ただしros1_bridgeの公式がgalacticまでなので、imageも同様にgalacticまでの提供です。
Humnble以降のディストリビューションでros1_bridgeを使いたい場合は、ここなどを参考にする必要がありそうです。

robot_state_publisherとjoint_state_publihser

robot_state_publisher

ロボットの各関節角度を入力(joint_statesというトピック)として得ることで、各関節の3次元位置をtf2のトピックとして出力する。ロボットのkinematic treeは、URDFを元にしている。

joint_state_publisher

ロボットの各関節に関する状態(位置、速度、力)をjoint_statesというトピックとして出力する。このノードがあるおかげで、ロボットの関節情報が明示され、ロボットの姿勢がわかる。

robot_state_publisherとjoint_state_publisherの関係

joint_state_publisher ー トピックjoint_states → robot_state_publisher
という関係になる。つまり、joint_state_publisherが素材となる情報をトピックとしてpublishし、それをrobot_state_publisherがURDFの情報を元にロボットの3次元位置情報に変換している構図になる

Docker・Dockerfile・Docker compose・entrypoint.shのメモ

最近Dockerを使って開発を行うことが多いので、諸々調べたことを加筆すると共に、適宜修正をしていきます。修正する際は、before/afterを残すようにしますが、私の認識違いや仕様変更などに伴って修正される可能性がある点はご容赦ください。

Docker関連

コンテナからGUIを表示させる方法

  1. ホストとコンテナで諸々共有する
  2. ホストコンピュータ上でxhost +local:を実行する
    • このコマンドを実行することで、localhost上のすべてのXクライアントがホストコンピュータのXサーバーにアクセス可能になる。
    • なおxhost +とだけすると、全世界から自分のXサーバーに対してアクセス可能になってしまうため要注意
    • 詳しくはhttps://zenn.dev/ykesamaru/articles/add7d844f56516私の過去の記事などを参照ください。

Dockerfile

Docker compose(docker-compose.ymlを使う想定)

ホストコンピュータのデバイスにアクセスしたい

  1. まず、デバイスファイルを共有する
  2. 次に、docker-compose.yml上でデバイスファイルにアクセスしたいアプリケーションに対して

privileged: true

を追加する。例えばこの記事のように。

docker-compose向けに環境変数を定義したい

.envファイル作成し、そこに定義する。参考: docker-composeのenv_fileと.envファイルの違い #Docker - Qiita

entrypoint.sh

entrypoint.shでは、コンテナ起動直後に実行したいコマンドなどを記述しておきます。例えばROSでは、ros_entrypoint.shのようにROS向けのentrypoint.shを作成し、その中では、

# setup ros environment
source "/opt/ros/$ROS_DISTRO/setup.bash"

のように記述します。他にも必要なコマンドがあれば追記しておきます。

ROSでcompressed imageをdecompressする方法(コマンドライン)

  • Image

rosrun image_transport republish compressed in:=/camera/image_raw raw out:=/camera/image_raw

  • Depth

rosrun image_transport republish compressedDepth in:=/camera/image_raw raw out:=/camera/image_raw

gitの使い方

git submodule

レポジトリに対し、別のレポジトリを関連付けるためのコマンドです。例えばhogeというレポジトリがあるとして、そのレポジトリに対して

git submodule add https://xxx.fuga.git

とすると、hogeレポジトリに

fuga@8fc2cdb

が登録されます。上記8fc2cdbは、hogeに関連付けたfugaのコミットコードです。これにより、hogeレポジトリがfugaレポジトリのどのコミットを利用しているかが明示できます。加えて、hogeをcloneなどした時に、fuga@8fc2cdbも取得できるようになります。

git filter-branch -> filter-repo

指定したファイルやディレクトリなどをコミットログから削除するためのコマンド。ただし、git標準のfilter-branchを使用すると、3rdパーティー製のfilter-repoを使うように促される。
なおUbuntuではfilter-repoは標準ではインストールされていないので、別途自分でインストールが必要である。