LoginSignup
4
3

NVIDIA SDK Manager docker + flash.sh によるL4TとJetson SDK Componentsインストール

Last updated at Posted at 2024-05-14

はじめに

NVIDIA SDK Manager dockerを使用し、以下3点をインストールする方法を紹介します。

・L4TのLinux Kernelに変更を加え作えビルドした.imgファイル(カスタムイメージと呼びます)
・Jetsonから読み取ったカスタムイメージ
・Jetson SDK Components

セットアップ環境の前提

ホストコンピュータは下記の記事でセットアップしたものを使用します。

カスタムイメージのインストール準備

カスタムイメージは、L4T Driver Package に含まれる flash.sh を使用しJetsonにインストールしますが、flash.sh はSDK Managerのプログラムを利用します。過去のバージョンのSDK ManagerはSDK ManagerをインストールするPC(ホストコンピュータと呼びます)のビデオドライバーやCUDAのバージョンをアップデートしなければならない仕様だったことが私のトラウマ(笑)になっており、ホストコンピュータに直接SDK Managerをインストールしたくありません。よって、SDK Manager Dockerを使用します。

SDK Manager Docker

SDK ManagerのDockerイメージはNVIDIAから配布されていますが、flash.sh を使用するにはひと手間が必要です。

まず、公式からDockerイメージをダウンロードします。注意点は次のとおりです。

  • 古いSDK Managerはユーザ認証に失敗するため、新しいバージョンをダウンロードします
  • イメージのUbuntuバージョンは、インストールするLinux KernelとJetPackのインストールに対応したものを選択します(ダウンロードページに対応表があります)

ホストコンピュータにDockerイメージをロードします。

.tar.gzのファイル名は、ダウンロードしたものに置き換えます。

docker load -i ~/Downloads/sdkmanager-2.1.0.11660-Ubuntu_18.04_docker.tar.gz

SDK Managerは、インストールファイルをビルドする際、Jetsonハードウェアの仮想化にQEMUを使用します。しかし、Jetsonのアーキテクチャであるaarch64のプロファイルがSDK Manager Dockerになく、プロファイルをイメージに加えます。また、ホストコンピュータがプロキシを経由してインターネットへ接続する環境下にあり、JetPackをダウンロードするためにプロキシサーバの設定を加えます。これらにDocker composeを使用します。

以下のファイルを準備します。

file.system
docker_sdkmanager
├── Dockerfile.sdk
├── build_sdk.sh
├── container_bind
│   ├── qemu-aarch64
│   └── setup_sdk.sh
└── docker-compose.yaml

sdkmanager:2.1.0.11660-Ubuntu_18.04 はダウンロードしたイメージファイルに変更します。

Dockerfile.sdk
FROM sdkmanager:2.1.0.11660-Ubuntu_18.04
 
ARG HTTP_PROXY
ARG HTTPS_PROXY
ARG L4T_WORKDIR
ARG CONTAINER_BIND
 
ENV http_proxy ${HTTP_PROXY}
ENV https_proxy ${HTTPS_PROXY}
ENV L4T_WORKDIR ${L4T_WORKDIR}
ENV CONTAINER_BIND ${CONTAINER_BIND}
 
RUN sudo touch /etc/apt/apt.conf.d/90proxy && \
    sudo echo 'Acquire::http::proxy "'${http_proxy}'";' | sudo tee -a /etc/apt/apt.conf.d/90proxy > /dev/null && \
    sudo echo 'Acquire::https::proxy "'${https_proxy}'";' | sudo tee -a /etc/apt/apt.conf.d/90proxy > /dev/null && \
    sudo echo 'Acquire::ftp::proxy "'${http_proxy}'";' | sudo tee -a /etc/apt/apt.conf.d/90proxy > /dev/null && \
    sudo echo 'Acquire::socks::proxy "'${http_proxy}'";' | sudo tee -a /etc/apt/apt.conf.d/90proxy > /dev/null

RUN sudo apt-get update -y
RUN sudo apt-get install -y --no-install-recommends \
    qemu-user-static \
    binfmt-support \
    binutils \
    wget

RUN wget https://github.com/qemu/qemu/raw/master/scripts/qemu-binfmt-conf.sh
RUN chmod +x qemu-binfmt-conf.sh
RUN sudo ./qemu-binfmt-conf.sh --qemu-path /usr/bin --qemu-suffix -static --debian

ENTRYPOINT []

公式のDockerイメージは ENTRYPOINTに sdkmanager --cli が指定されていますが、flash.sh なども使用するためENTRYPOINTを無しにします。

build_sdk.sh
#!/bin/bash

docker-compose build \
    --build-arg HTTP_PROXY=${http_proxy} \
    --build-arg HTTPS_PROXY=${https_proxy} \
    using_jetpack

docker-compose run --name using_jetpack_${USER} using_jetpack /bin/bash -c '${CONTAINER_BIND}/setup_sdk.sh'
docker container commit using_jetpack_${USER} jetpack_setup
docker container rm using_jetpack_${USER}
qemu-aarch64.
package qemu-user-static
interpreter /usr/bin/qemu-aarch64-static
flags: OC
offset 0
magic \x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00
mask \xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff
setup_sdk.sh
#!/bin/bash

sudo mkdir -p ${L4T_WORKDIR}
sudo chown nvidia:root ${L4T_WORKDIR}

sudo cp "${CONTAINER_BIND}/qemu-aarch64" /usr/share/binfmts/
sudo mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
sudo update-binfmts --enable qemu-aarch64
docker-compose.yaml
version: "3.7"
 
services:
  using_jetpack:
    image: jetpack_setup
    privileged: true
    build: 
      context: ./
      dockerfile: ./Dockerfile.sdk
      args:
        - HTTP_PROXY=${http_proxy}
        - HTTPS_PROXY=${https_proxy}
        - L4T_WORKDIR=/tmp/nvidia/sdkm_downloads
        - CONTAINER_BIND=/var/container_bind
    volumes:
      - type: bind
        source: /dev
        target: /dev
      - type: bind
        source: /dev/bus/usb
        target: /dev/bus/usb
      - type: bind
        source: /media/${USER}
        target: /media/nvidia:slave
      - type: volume
        source: jetpack_temporary
        target: /tmp/nvidia
      - type: bind
        source: ./container_bind
        target: /var/container_bind
    network_mode: host

volumes:
  jetpack_temporary:

Dockerイメージをビルドします。

chmod +x build_sdk.sh ./container_bind/setup_sdk.sh
./build_sdk.sh

JetPack Components

通常、SDK Managerを実行すると、NVIDIAサイトのログインを要求されます。これは、JetPack Componentsをダウンロードするためですが、一度ダウンロードしてしまえば使い回しができ、インストールする度にログインする必要がありません。よって、JetPack Componentsをダウンロードしておきます。ダウンロード先はDockerボリュームを指定するため、ダウンロードファイルはDockerコンテナを停止しても残存します。リフレッシュしたい場合は、Dockerボリュームを削除するだけです。

JETPACK_VERSION='4.5.1'
TARGET_HARDWARE='JETSON_XAVIER_NX'
docker-compose run --rm using_jetpack sdkmanager \
    --cli \
    --action downloadonly \
    --download-folder /tmp/nvidia/sdkm_downloads \
    --archived-versions \
    --login-type devzone \
    --product Jetson \
    --target-os Linux \
    --version ${JETPACK_VERSION} \
    --target ${TARGET_HARDWARE} \
    --flash skip \
    --license accept \
    --stay-logged-in false \
    --collect-usage-data disable \
    --exit-on-finish
  • この時点で、SDK ManagerからJetsonにJetPackをインストールする環境が整います。L4TのLinux Kernelを含めたJetPackをフルインストールする場合は、リカバリーモードでJetsonを起動し、USBケーブルでJetsonとホストコンピュータを接続し、以下のコマンドを実行します

    docker-compose run --rm using_jetpack sdkmanager \
        --cli \
        --action install \
        --check-for-updates false \
        --login-type offline \
        --download-folder /tmp/nvidia/sdkm_downloads \
        --archived-versions \
        --product Jetson \
        --target-os Linux \
        --version ${JETPACK_VERSION} \
        --target ${TARGET_HARDWARE} \
        --flash all \
        --license accept \
        --stay-logged-in false \
        --collect-usage-data disable \
        --exit-on-finish
    
  • SDK Managerのオプションは頻繁に変わるため、オプションは公式で調べます

    https://docs.nvidia.com/sdk-manager/archives/index.html

    バージョンを選択 > Install with the Command Line > General Arguments

  • SDK Managerは基本的に最新バージョンと1つ前のJetPackに対応していますが、--archived-versions オプションを加える事で過去のバージョンも利用可能になります

L4T Driver Package & Sample RootFs

公式からL4T Driver PackageとSample RootFsをダウンロードします。

以下のファイルを準備します。

  • Tegra186_Linux_R32.5.1_aarch64.tbz2 はダウンロードしたL4T Driver Packageに置き換えます
  • Tegra_Linux_Sample-Root-Filesystem_R32.5.1_aarch64.tbz2 はダウンロードしたSample RootFsに置き換えます
  • docker-compose.yamlusing_flash サービスを追記します
file.system
docker_sdkmanager
├── Dockerfile.l4t
├── Dockerfile.sdk
├── build_l4t.sh
├── build_sdk.sh
├── container_bind
│   ├── Tegra186_Linux_R32.5.1_aarch64.tbz2
│   ├── Tegra_Linux_Sample-Root-Filesystem_R32.5.1_aarch64.tbz2
│   ├── qemu-aarch64
│   ├── setup_l4t.sh
│   └── setup_sdk.sh
└── docker-compose.yaml
Dockerfile.l4t
FROM jetpack_setup
 
ARG L4T_DRIVERS
ARG L4T_SAMPLE_ROOTFS
ARG L4T_BOARD
ARG L4T_PARTITION

ENV L4T_DRIVERS ${L4T_DRIVERS}
ENV L4T_SAMPLE_ROOTFS ${L4T_SAMPLE_ROOTFS}
ENV L4T_BOARD ${L4T_BOARD}
ENV L4T_PARTITION ${L4T_PARTITION}

ENTRYPOINT []
build_l4t.sh
#!/bin/bash

if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ] || [ -z "$4" ]; then
    echo "Error: Missing arguments."
    echo "Usage: $0 <l4t_drivers> <l4t_sample_rootfs> <board> <partition>"
    echo "Example(Product Module): $0 'Tegra186_Linux_R32.5.1_aarch64.tbz2' 'Tegra_Linux_Sample-Root-Filesystem_R32.5.1_aarch64.tbz2' 'jetson-xavier-nx-devkit-emmc' 'mmcblk0p1'"
    echo "Example(Devkit): $0 'Tegra186_Linux_R32.5.1_aarch64.tbz2' 'Tegra_Linux_Sample-Root-Filesystem_R32.5.1_aarch64.tbz2' 'jetson-xavier-nx-devkit' 'mmcblk0p1'"
    exit 1
fi

docker-compose build \
    --build-arg L4T_DRIVERS=$1 \
    --build-arg L4T_SAMPLE_ROOTFS=$2 \
    --build-arg L4T_BOARD=$3 \
    --build-arg L4T_PARTITION=$4 \
    using_flash

docker-compose run --name using_flash_${USER} using_flash /bin/bash -c '${CONTAINER_BIND}/setup_l4t.sh'
docker container commit using_flash_${USER} l4t_setup
docker container rm using_flash_${USER}
setup_l4t.sh
#!/bin/bash

echo -n 'unpack l4t drivers and sample rootfs ...'
sudo tar xpf "${CONTAINER_BIND}/${L4T_DRIVERS}" -C "${L4T_WORKDIR}/"
echo -n ' doing ...'
sudo tar xpf "${CONTAINER_BIND}/${L4T_SAMPLE_ROOTFS}" -C "${L4T_WORKDIR}/Linux_for_Tegra/rootfs/"
echo ' done'

cd ${L4T_WORKDIR}/Linux_for_Tegra

sudo ./apply_binaries.sh
sudo ./flash.sh --no-flash ${L4T_BOARD} ${L4T_PARTITION}
docker-compose.yaml
version: "3.7"
 
services:
  using_jetpack:
    image: jetpack_setup
    privileged: true
    build: 
      context: ./
      dockerfile: ./Dockerfile.sdk
      args:
        - HTTP_PROXY=${http_proxy}
        - HTTPS_PROXY=${https_proxy}
        - L4T_WORKDIR=/tmp/nvidia/sdkm_downloads
        - CONTAINER_BIND=/var/container_bind
    volumes:
      - type: bind
        source: /dev
        target: /dev
      - type: bind
        source: /dev/bus/usb
        target: /dev/bus/usb
      - type: bind
        source: /media/${USER}
        target: /media/nvidia:slave
      - type: volume
        source: jetpack_temporary
        target: /tmp/nvidia
      - type: bind
        source: ./container_bind
        target: /var/container_bind
    network_mode: host

  using_flash:
    image: l4t_setup
    privileged: true
    build: 
      context: ./
      dockerfile: ./Dockerfile.l4t
      args:
        - L4T_DRIVERS
        - L4T_SAMPLE_ROOTFS
        - L4T_BOARD
        - L4T_PARTITION
    volumes:
      - type: bind
        source: /dev
        target: /dev
      - type: bind
        source: /dev/bus/usb
        target: /dev/bus/usb
      - type: bind
        source: /media/${USER}
        target: /media/nvidia:slave
      - type: volume
        source: jetpack_temporary
        target: /tmp/nvidia
      - type: bind
        source: ./container_bind
        target: /var/container_bind
    network_mode: host

volumes:
  jetpack_temporary:

Dockerイメージをビルドします。

chmod +x build_l4t.sh ./container_bind/setup_l4t.sh
./build_l4t.sh 'Tegra186_Linux_R32.5.1_aarch64.tbz2' 'Tegra_Linux_Sample-Root-Filesystem_R32.5.1_aarch64.tbz2' 'jetson-xavier-nx-devkit' 'mmcblk0p1'

これで、NVIDIA公式のL4Tをインストールする準備が整いました。あとは、手を加えたL4Tの .img や、Jetsonから読み取った .img ファイルに置き換えます。.img や L4T Driver Packageなどは、Dockerコンテナから参照できる /tmp/nvidia/Linux_for_Tegra にあります。例えば、custom.img に置き換える場合は次のように実行します。JetPack Components同様、Jetsonにインストールするファイルや custom.img はDockerボリュームに保存されるため、Dockerコンテナを停止しても残存します。

docker-compose run --rm using_flash /bin/bash -c 'cd "${L4T_WORKDIR}/Linux_for_Tegra" && sudo cp "${CONTAINER_BIND}/custom.img" ./bootloader/system.img'

L4T_WORKDIR 等の変数はビルドの際Dockerイメージに組み込んでいます。

L4T インストール

リカバリーモードでJetsonを起動し、JetsonとホストコンピュータをUSBケーブルで接続し、flash.sh を実行します。

docker-compose run --rm using_flash /bin/bash -c 'cd "${L4T_WORKDIR}/Linux_for_Tegra" && sudo ./flash.sh ${L4T_BOARD} ${L4T_PARTITION}'

Jetson SDK Components インストール

Jetson SDK ComponentsはJetPack Componentsの一部であり、Deep Learningや画像処理などGPGPUの恩恵を受けられる計算においてJetsonのリソースを効率よく使用するためのコンポーネントや、Jetson上の開発を支援するツール等がパッケージされたものです。flash.sh は、L4TをJetsonにインストールするスクリプトであり、Jetson SDK Componentsを使用する場合別途インストールしなければなりません。ただし、Jetsonから読み取った .img をインストールした場合は、読み取る前にインストールしたJetson SDK Componentsなどのパッケージが含まれています。

docker-compose run --rm using_jetpack sdkmanager \
    --cli \
    --action install \
    --check-for-updates false \
    --login-type offline \
    --download-folder /tmp/nvidia/sdkm_downloads \
    --archived-versions \
    --product Jetson \
    --target-os Linux \
    --version ${JETPACK_VERSION} \
    --deselect 'Jetson OS' \
    --select 'Jetson SDK Components' \
    --target ${TARGET_HARDWARE} \
    --flash all \
    --license accept \
    --stay-logged-in false \
    --collect-usage-data disable \
    --exit-on-finish

おまけ Jetsonからsystem.imgを読み取る方法

JetsonのメインストレージであるeMMC/SD-Cardなどは、bootloaderやDeviceTree、APP等のパーティションがあり、ここではルートファイルシステムが記憶されているAPPパーティションのみを読み取ります。
リカバリーモードでJetsonを起動し、USBケーブルでJetsonとホストコンピュータを接続し、flash.sh を実行します。

docker-compose run --rm using_flash /bin/bash -c 'cd "${L4T_WORKDIR}/Linux_for_Tegra" && sudo ./flash.sh -r -k APP -G custom.img ${L4T_BOARD} ${L4T_PARTITION}'

参考文献

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3