aptpod Tech Blog

株式会社アプトポッドのテクノロジーブログです

【連載 ROS Tips】ROSのDockerコンテナからNVIDIA GPUを利用するには

アプトポッド 組み込みエンジニアの久保田です。

連載の前回 では、ROSの開発においてDockerをどのように活用するかを紹介しました。その中で触れた通り、Dockerコンテナを使ってホストのハードウェアリソースにアクセスすることが可能です。例えば、当社で販売している車載向けエッジコンピュータ EDGEPLANT T1 はNVIDIA Jetson TX2を搭載しています。NVIDIA Jetsonシリーズは、GPUを搭載しており、AIやディープラーニングのタスクに適しています。このJetsonのGPUをDockerコンテナ内で最大限に活用するために、NVIDIAが提供する公式Dockerイメージの使用が推奨されています。

ROS開発において、この公式Dockerイメージは導入しやすい反面、ROS自体がソースコードからビルドされており、ROS公式に提供されているdebianパッケージを利用することができません。この制限を解消するためには、NVIDIA GPU資源を利用でき、かつROS公式に提供されているdebianパッケージの利用可能なDockerイメージの作成が必要となります。

連載ROS Tips第3回目となる今回は、ROSのDockerコンテナからのNVIDIA GPU利用方法を紹介します。


なお、連載の予定として、以下のようなコンテンツを予定しております。(連載内容は、変更・追加の可能性があります。ご了承ください)


本連載の投稿済みの記事はこちらからご覧いただけます。

tech.aptpod.co.jp

tech.aptpod.co.jp



コンテナからNVIDIA GPUを利用するには

DockerコンテナからNVIDIA GPUを利用するには、NVIDIA Container Runtimeが必要です。

https://miro.medium.com/v2/resize:fit:640/format:webp/1*6E0EiTQ3g0DkTckA4P-_eg.png

Enabling GPUs with NVIDIA Docker Container Runtime

NVIDIA Container Runtimeは、Dockerなどのコンテナ技術とNVIDIA GPUを統合するためのツールです。これにより、GPUを活用したアプリケーションをコンテナ内で簡単に実行することができます。NVIDIAのGPUドライバと連携して、コンテナ内からGPUリソースにアクセスするために必要なライブラリやバイナリを提供し、ディープラーニングや機械学習、高性能計算などのGPUを活用したタスクを、コンテナ化された環境で効率的に実行することができます。

NVIDIA Container Runtimeの特徴:

  • GPUアクセス: コンテナからNVIDIA GPUへの直接アクセスが可能になります。
  • 互換性: DockerやKubernetesなどの主要なコンテナ技術との互換性があります。
  • 柔軟性: 複数のGPUや異なるGPUアーキテクチャに対応しています。


NVIDIA Container Runtimeの使用方法

NVIDIA公式サイトで示されている手順を紹介します。

NVIDIA Container RuntimeによりDockerコンテナ内でGPUを利用するためには、Dockerコンテナを実行するホストでインストール・設定などの準備が必要です。 なお、JetsonシリーズではJetPackをインストールすることによりNVIDIA Container Runtimeを利用することができますので、ここでご紹介する手順でのインストール・設定は不要です。

docs.nvidia.com

まず、リポジトリを設定します。

curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
  && curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
    sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
    sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list \
  && \
    sudo apt-get update

次に、NVIDIA Container Runtimeをインストールします。

sudo apt-get install -y nvidia-container-toolkit

さらに、Dockerの設定を変更します。

sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker

最後に、NVIDIA Container Runtimeを実行します。

docker run --rm \
    --runtime=nvidia \
    --gpus all \
    arm64v8/ubuntu:22.04 \
    nvidia-smi

上記で使用するコマンドの引数は以下の情報を参考にしてください。

引数 説明
runtime ランタイムの指定 (nvidia)
gpus 使用GPU指定 ( all : すべてのGPU )

docs.nvidia.com


GPU状態の確認方法

GPUの状態を確認するために通常はnvidia-smiコマンドが使用されますが、Jetsonシリーズでは使用できません。 JetsonシリーズでGPUの状態を表示するためには、jtopコマンドが便利です。

github.com

jtopコマンドを実行するには、json-stats をインストールが必要です。

sudo apt install -y python3-pip
sudo pip3 install -U jetson-stats

jtopコマンドを実行します。

jtop

https://github.com/rbonghi/jetson_stats/raw/master/docs/images/jtop.png


ROSコンテナからNVIDIA GPUを利用するには(NVIDIA公式イメージの使用)

JetsonシリーズでROSのDockerコンテナを起動しコンテナ内からGPUを活用する場合、NVIDIA公式イメージの使用が推奨されています。

公式イメージの提供サイト:


ROS安定版に対して、NVIDIA公式イメージで使用できるタグ

公式イメージでは、ROSの各ディストリビューション用にタグがいくつか公開されています。 ここでは、ROSの最新の安定版ディストリビューション(LTS)に対応するタグを紹介します。

ROS Distro L4T Ubuntu イメージのタグ
ROS Noetic R32.7.1 18.04 dustynv/ros:noetic-ros-base-l4t-r32.7.1
R34.1.1 20.04 dustynv/ros:noetic-ros-base-l4t-r34.1.1
R35.4.1 20.04 dustynv/ros:noetic-ros-base-l4t-r35.4.1
ROS2 Humble R32.7.1 18.04 dustynv/ros:humble-ros-base-l4t-r32.7.1
R34.1.1 20.04 dustynv/ros:humble-ros-base-l4t-r34.1.1
R35.4.1 20.04 dustynv/ros:humble-ros-base-l4t-r35.4.1


公式イメージではROSパッケージをリポジトリから追加できない

これらの公式イメージは、ベースとするUbuntuのイメージにROSをソースコードビルドでインストールして構成されています。ROSは各ディストリビューションで前提とするUbuntuバージョンがそれぞれ決まっていますが、NVIDIA公式イメージではROSディストリビューションが前提としているUbuntuバージョンとベースイメージのUbuntuバージョンが異なる場合があり、そういった場合にdebパッケージによるROSのインストールが行えなえません。

この影響により、公式イメージに新しいROSパッケージを追加する際、Ubuntuの公式リポジトリを用いてaptコマンドで直接追加することができません。ROSの追加機能やパッケージを導入したい場合は、GitHubなどからソースコードを取得して手動でビルドする必要があります。

NVIDIA公式イメージの仕組み

先のセクションで利用するために、公式イメージがどのように作られているのか、中身を調べていきます。

NVIDIAが提供している公式イメージは、L4T rootファイルシステムに含まれるパッケージのサブセットで構成された l4t-base というイメージをベースにしています。l4t-base は、Jetsonシリーズで実行することを想定しており、NVIDIA Container Runtime を使用してコンテナ内でL4Tアプリケーションを実行できるようにします。

ハードウェア依存性を提供するプラットフォーム固有のライブラリと、特定デバイスのデバイスファイルをNVIDIA Container Runtimeによってコンテナにマウントし、コンテナ内で実行するL4Tアプリケーションに提供します。マウントされるライブラリは /etc/nvidia-container-runtime/host-files-for-container.d/l4t.csv に記載されています。

ベースイメージの提供サイト:


l4t-baseイメージの Dockerfile は次のような構成となっており、以降ではこの Dockerfile について解説します。

  • ベースイメージの指定
  • パッケージのインストール
  • NVIDIAの公開鍵の追加
  • NVIDIAのリポジトリの追加
  • Tegraライブラリの設定
  • EGLの設定
  • GPU関連環境変数の設定


ベースイメージの指定

FROM docker.io/arm64v8/ubuntu:18.04

ARM64アーキテクチャのUbuntuイメージをベースイメージとして指定します。 Ubuntuの安定版(LTS)のイメージとして、以下のようなものがあります。

Ubuntu バージョン Distro イメージのタグ
22.04 Jammy arm64v8/ubuntu:22.04
20.04 Focal arm64v8/ubuntu:20.04
18.04 Bionic arm64v8/ubuntu:18.04


パッケージのインストール

RUN apt-get update && \
    apt-get upgrade -y && \
    apt-get install -qq -y --no-install-recommends \
    bc \
    bzip2 \
    can-utils \
    freeglut3-dev \
    gstreamer1.0-alsa \
    gstreamer1.0-libav \
    gstreamer1.0-plugins-bad \
    gstreamer1.0-plugins-base \
    gstreamer1.0-plugins-good \
    gstreamer1.0-plugins-ugly \
    gstreamer1.0-tools \
    i2c-tools \
    iw \
    kbd \
    kmod \
    language-pack-en-base \
    libapt-inst2.0 \
    libcanberra-gtk3-module \
    libgles2 \
    libglu1-mesa-dev \
    libglvnd-dev \
    libgtk-3-0 \
    libpython2.7 \
    libudev1 \
    libvulkan1 \
    libzmq5 \
    mtd-utils \
    parted \
    pciutils \
    python \
    python-pexpect \
    python3-distutils \
    sox \
    udev \
    vulkan-utils \
    wget \
    wireless-tools wpasupplicant && \
    rm -rf /var/lib/apt/lists/* && apt-get clean

GstreamerやOpenGL関連のライブラリ、ワイヤレスツール、PythonなどGPU利用に関連するパッケージをインストールします。L4Tアプリケーションの実行に必要な最低限のパッケージとなっています。


NVIDIAの公開鍵の追加

COPY jetson-ota-public.key /etc/jetson-ota-public.key
RUN apt-key add /etc/jetson-ota-public.key

NVIDIAの公開鍵をコンテナにコピーし、パッケージ管理ツール apt に鍵を追加します。


NVIDIAのリポジトリの追加

RUN echo "deb https://repo.download.nvidia.com/jetson/common $RELEASE main" >> /etc/apt/sources.list

NVIDIAのJetson用リポジトリを追加します。環境変数 RELEASE には r32.7 などリリースバージョンを指定します。


Tegraライブラリの設定

RUN echo "/usr/lib/aarch64-linux-gnu/tegra" >> /etc/ld.so.conf.d/nvidia-tegra.conf && \
    echo "/usr/lib/aarch64-linux-gnu/tegra-egl" >> /etc/ld.so.conf.d/nvidia-tegra.conf

Tegra関連のライブラリのパスをldconfigの設定に追加します。


EGLの設定

RUN rm /usr/share/glvnd/egl_vendor.d/50_mesa.json
RUN mkdir -p /usr/share/glvnd/egl_vendor.d/ && echo '\
{\
    "file_format_version" : "1.0.0",\
    "ICD" : {\
        "library_path" : "libEGL_nvidia.so.0"\
    }\
}' > /usr/share/glvnd/egl_vendor.d/10_nvidia.json

RUN mkdir -p /usr/share/egl/egl_external_platform.d/ && echo '\
{\
    "file_format_version" : "1.0.0",\
    "ICD" : {\
        "library_path" : "libnvidia-egl-wayland.so.1"\
    }\
}' > /usr/share/egl/egl_external_platform.d/nvidia_wayland.json

RUN ldconfig

NVIDIAのEGL (Embedded-System Graphics Library)とWaylandの設定を追加します。


GPU関連環境変数の設定

ENV NVIDIA_VISIBLE_DEVICES all
ENV NVIDIA_DRIVER_CAPABILITIES all

NVIDIA Container Runtimeから使用できるデバイスとドライバの機能をすべて有効にします。


NVIDIA GPUを使用しつつ、ROSパッケージをリポジトリ追加可能にするには

前述した通り、Jetsonシリーズでは、NVIDIAの公式イメージの使用が推奨されています。このイメージでは、ベースとするUbuntuイメージのバージョンとROSディストリビューションが前提とするUbuntuバージョンが異なることが理由でROSをソースコードからビルドしてインストールしているため、本来対応しているUbuntuバージョンの公式リポジトリを用いてaptコマンドでROSパッケージを直接追加することはできません。

この制限を克服する方法として、ホストOSのUbuntuバージョンとは異なるバージョンをベースにした非公式イメージを使用する方法が考えられます。

非公式Ubuntu 20.04ベースイメージの提供サイト

非公式Ubuntu 22.04ベースイメージの提供サイト

これらの非公式イメージは、任意のバージョンのUbuntuイメージをNVIDIA GPUに対応させるために、任意のバージョンのUbuntuイメージをベースとして、NVIDIA Container Runtimeを使用するために必要なツールをインストールしています。これらのNVIDIA GPU対応のUbuntuベースイメージに、さらにROSディストリビューションをインストールすればNVIDIA GPUに対応したROSコンテナができあがります。


当社リポジトリで提供開始するイメージのご紹介

上記で紹介した非公式イメージは、別々の開発者が Ubuntu 20.04、Ubuntu 22.04 それぞれに向けて、各自のリポジトリで提供しているものです。

今回、より汎用的に任意のUbuntuバージョンで利用できるコンテナイメージ用のDockerfileを当社にて作成し、提供を開始いたしますのでご紹介します。

Dockerfileの提供サイト

GitHub - aptpod/l4t-ros: NVIDIA L4T (Linux for Tegra) enabled ROS Container Image

こちらは、当社が販売している Jetson TX2 を搭載したエッジコンピュータ EDGEPLANT T1 でご利用いただくことを想定して作成したものですが、Jetsonシリーズを搭載したコンピュータであれば同様にご利用いただけるはずです。

GitHubには、ROS 2用だけでなく、ROS 1用のDockerfileも用意しています。GPUを活用したROSコンテナを利用したい場合に是非ご活用ください。

なお、今回GitHubで公開したDockerfileは Apache 2.0 ライセンスにて公開しており、基本的には自己責任にて使用していただく想定です。とはいえ、なるべく当社でメンテナンスしていく予定ですので、もし不具合等ございましたら当社までご連絡ください。

より詳しい技術情報は、リポジトリのREADMEをご覧ください。


Jetson TX2搭載エッジコンピュータ EDGEPLANT T1 のご紹介

EDGEPLANT T1

上記のDockerfileにて作成したイメージは、Jetsonシリーズを搭載したコンピュータであればご利用いただけるはずですが、基本的には当社が販売している Jetson TX2 を搭載したエッジコンピュータ EDGEPLANT T1 でご利用いただくことを想定したものになります。

EDGEPLANT T1はNVIDIA Jetson TX2を搭載したエッジコンピュータで、映像のエンコードやデコードなどGPUを使用する処理や、デバイスエッジでのAIモデルの実行用途にお使いいただけます。また、SIMスロット、GPSモジュールなど、IoT端末として必要な様々な機能を備えています。車載機器に求められるEMC規格(Eマーク)、信頼性規格(JASO D014)などにも準拠しており、ROSを使用したロボット開発、自動運転システムの開発にもおすすめです。

EDGEPLANT T1は、当社の販売パートナー様または、Amazon.co.jp からご購入いただけます。詳しくは、製品ページをご覧ください。

www.aptpod.co.jp

今回ご紹介したイメージを EDGEPLANT T1 上でご利用いただく場合であれば当社からの技術サポートも可能です。 コンテナイメージ上でのNVIDIA GPUを活用したROSアプリケーションの開発をご検討の方は、EDGEPLANT T1 の採用も是非ご検討ください。


当社提供イメージの仕組み

以降では、提供開始するDockerfileの構成について解説します。

ご紹介するコンテナイメージは、これまでにご紹介したUbuntuの任意のバージョンをNVIDIA GPUに対応させる方法に加え、ROSの利用に必要なセットアップを行ったものです。 ROSコンテナの公式イメージの Dockerfile は次のサイトで提供されていますので、こちらを参考にセットアップを行います。

ROSの公式イメージの提供サイト:

このテックブログでは、NVIDIA GPUを利用できる ROS2 Humble - L4T 32.7.1 のコンテナ構成ファイルを紹介します。

L4Tベースイメージ (Container tag: l4t-base:jammy-r32.7)

FROM docker.io/arm64v8/ubuntu:22.04

ARG RELEASE="r32.7"
ARG SOC="t186"

ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
    apt-get upgrade -y && \
    apt-get install -qq -y --no-install-recommends \
    bc \
    bzip2 \
    can-utils \
    ca-certificates \
    freeglut3-dev \
    gstreamer1.0-alsa \
    gstreamer1.0-libav \
    gstreamer1.0-plugins-bad \
    gstreamer1.0-plugins-base \
    gstreamer1.0-plugins-good \
    gstreamer1.0-plugins-ugly \
    gstreamer1.0-tools \
    i2c-tools \
    iw \
    kbd \
    kmod \
    language-pack-en-base \
    libapt-inst2.0 \
    libcanberra-gtk3-module \
    libgles2 \
    libglu1-mesa-dev \
    libglvnd-dev \
    libgtk-3-0 \
    libpython2.7 \
    libudev1 \
    libvulkan1 \
    libzmq5 \
    mtd-utils \
    parted \
    pciutils \
    python \
    python-pexpect \
    python3-distutils \
    sox \
    udev \
    vulkan-utils \
    wget \
    wireless-tools wpasupplicant && \
    rm -rf /var/lib/apt/lists/* && apt-get clean

ADD --chown=root:root https://repo.download.nvidia.com/jetson/jetson-ota-public.asc /etc/apt/trusted.gpg.d/jetson-ota-public.asc
RUN chmod 644 /etc/apt/trusted.gpg.d/jetson-ota-public.asc && \
    echo "deb https://repo.download.nvidia.com/jetson/common $RELEASE main" >> /etc/apt/sources.list && \
    echo "deb https://repo.download.nvidia.com/jetson/$SOC $RELEASE main" >> /etc/apt/sources.list

RUN echo "/usr/lib/aarch64-linux-gnu/tegra" >> /etc/ld.so.conf.d/nvidia-tegra.conf && \
    echo "/usr/lib/aarch64-linux-gnu/tegra-egl" >> /etc/ld.so.conf.d/nvidia-tegra.conf

RUN rm /usr/share/glvnd/egl_vendor.d/50_mesa.json
RUN mkdir -p /usr/share/glvnd/egl_vendor.d/ && echo '\
{\
    "file_format_version" : "1.0.0",\
    "ICD" : {\
        "library_path" : "libEGL_nvidia.so.0"\
    }\
}' > /usr/share/glvnd/egl_vendor.d/10_nvidia.json

RUN mkdir -p /usr/share/egl/egl_external_platform.d/ && echo '\
{\
    "file_format_version" : "1.0.0",\
    "ICD" : {\
        "library_path" : "libnvidia-egl-wayland.so.1"\
    }\
}' > /usr/share/egl/egl_external_platform.d/nvidia_wayland.json

RUN echo "/usr/local/cuda-10.0/targets/aarch64-linux/lib" >> /etc/ld.so.conf.d/nvidia.conf

ARG CUDA=invalid

COPY ./dst/bin /usr/local/cuda-$CUDA/bin
COPY ./dst/nvvm /usr/local/cuda-$CUDA/nvvm
COPY ./dst/nvvmx /usr/local/cuda-$CUDA/nvvmx
COPY ./dst/include /usr/local/cuda-$CUDA/targets/aarch64-linux/include
COPY ./dst/lib64/stubs /usr/local/cuda-$CUDA/targets/aarch64-linux/lib/stubs
COPY ./dst/lib64/libcudadevrt.a /usr/local/cuda-$CUDA/targets/aarch64-linux/lib/
COPY ./dst/lib64/libcudart_static.a /usr/local/cuda-$CUDA/targets/aarch64-linux/lib/

RUN ln -s /usr/local/cuda-$CUDA /usr/local/cuda && \
    ln -s /usr/local/cuda-$CUDA/targets/aarch64-linux/include /usr/local/cuda/include && \
    ln -s /usr/local/cuda-$CUDA/targets/aarch64-linux/lib /usr/local/cuda/lib64

ENV PATH /usr/local/cuda-$CUDA/bin:/usr/local/cuda/bin:${PATH}
ENV LD_LIBRARY_PATH /usr/local/cuda-$CUDA/targets/aarch64-linux/lib:${LD_LIBRARY_PATH}

RUN ldconfig

ENV NVIDIA_VISIBLE_DEVICES all
ENV NVIDIA_DRIVER_CAPABILITIES all

CMD ["/bin/bash"]


ベースイメージを利用したROS2 Humbleイメージ (l4t-ros:humble-ros-core-r32.7)

また、L4Tベースイメージを利用して、任意のROSコンテナを作成するためのDockerfileのテンプレートも用意しました。

FROM l4t-base:jammy-r32.7

# setup timezone
RUN echo 'Etc/UTC' > /etc/timezone && \
    ln -s /usr/share/zoneinfo/Etc/UTC /etc/localtime && \
    apt-get update && \
    apt-get install -q -y --no-install-recommends tzdata && \
    rm -rf /var/lib/apt/lists/*

# install packages
RUN apt-get update && apt-get install -q -y --no-install-recommends \
    dirmngr \
    gnupg2 \
    && rm -rf /var/lib/apt/lists/*

# setup sources.list
RUN echo "deb http://packages.ros.org/ros2/ubuntu jammy main" > /etc/apt/sources.list.d/ros2-latest.list

# setup keys
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654

# setup environment
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8

ENV ROS_DISTRO humble

# install ros2 packages
RUN apt-get update && apt-get install -y --no-install-recommends \
    ros-humble-ros-core=0.10.0-1* \
    && rm -rf /var/lib/apt/lists/*

# setup entrypoint
COPY ./ros_entrypoint.sh /

ENTRYPOINT ["/ros_entrypoint.sh"]
CMD ["bash"]


ご紹介したイメージは、コンテナ内でGPUを利用するためにNVIDIA Container Runtimeを使用しています。 このため、一部のdebパッケージ・ライブラリはNVIDIA Container Runtimeが想定しているソフトウェアのバージョンとの不整合によりうまく動作しない場合があります。 現時点で、以下のパッケージが正常に動作しないことを確認しております。(今後、こちらのパッケージも使用可能となるよう修正を加えていく予定です)

バージョン不整合により動作しないパッケージ(記事公開時点で確認済みのもの)

  • GStreamer
  • OpenCV


まとめ

今回は、ROSのDockerコンテナでのNVIDIA GPUの利用方法について解説しました。 NVIDIA は Machine Learning やAI用の公式イメージを提供していますが、このGPU利用の仕組みを理解することで、 まだ提供されていない機能を持つコンテナイメージを作成することもできる用になります。

また、当社によるDockerfileの提供開始についてもお知らせしました。 Ubuntuの公式リポジトリを通じてROSパッケージを追加することが可能になることで、皆様の開発効率向上の手助けになれば幸いです。

連載の次回は

  • ROS 2を利用する上での大容量データ転送シナリオにおけるチューニングについての紹介

を予定しています。


当社プロダクトのご案内

先日行われた ROSConJP 2023 では、ROSの開発ワークフローを効率化するDXソリューションとして、新たなソリューションを発表いたしました。詳細については、ROSConJP 2023の参加報告記事をご覧ください。

tech.aptpod.co.jp

また、ROS開発において、当社プロダクトをどの様にご活用いただけるかは、連載1日目にて当社のVPoPがより詳しく紹介しておりますので、こちらもご覧ください。

tech.aptpod.co.jp

さらに、当社では、モビリティ・ロボットのフリート管理や遠隔監視、遠隔制御を実現するための管制制御システム向けのソリューションフレームワーク「intdash CONTROL CENTER」を提供しています。

tech.aptpod.co.jp

スマートシティにおける自動運転車、工場や物流倉庫における搬送ロボット、建設現場における建設機械など、モビリティ群の統合遠隔監視・管理、遠隔制御システムな どでお困りのことがあれば、ぜひお声掛けください。

お問合せフォームは こちら です。