From cf8108965cb471a9cd501b64959b75efa76da656 Mon Sep 17 00:00:00 2001 From: Alexandru Costache Date: Fri, 8 Aug 2025 09:27:57 +0000 Subject: [PATCH] Re-work examples to drop balenalib usage Since base images are no longer provided, we switch to using upstream Docker base images on top of which we enable udev. Change-type: minor Author: Alan Boris Signed-off-by: Alan Boris Signed-off-by: Alexandru Costache --- jetson-agx-orin-devkit/Dockerfile | 91 ------------------------------- jetson-nano/Dockerfile | 35 +++++++++++- jetson-nano/entry.sh | 87 +++++++++++++++++++++++++++++ jetson-orin/Dockerfile | 27 +++++++-- jetson-orin/entry.sh | 70 ++++++++++++++++++++++++ jetson-orin/startxfce.sh | 33 +++++++++++ jetson-tx2/Dockerfile | 39 ++++++++++++- jetson-tx2/entry.sh | 87 +++++++++++++++++++++++++++++ jetson-xavier-agx/Dockerfile | 40 +++++++++++--- jetson-xavier-agx/entry.sh | 87 +++++++++++++++++++++++++++++ jetson-xavier-nx/Dockerfile | 40 +++++++++++++- jetson-xavier-nx/entry.sh | 87 +++++++++++++++++++++++++++++ 12 files changed, 610 insertions(+), 113 deletions(-) delete mode 100644 jetson-agx-orin-devkit/Dockerfile create mode 100644 jetson-nano/entry.sh create mode 100644 jetson-orin/entry.sh create mode 100644 jetson-orin/startxfce.sh create mode 100644 jetson-tx2/entry.sh create mode 100644 jetson-xavier-agx/entry.sh create mode 100644 jetson-xavier-nx/entry.sh diff --git a/jetson-agx-orin-devkit/Dockerfile b/jetson-agx-orin-devkit/Dockerfile deleted file mode 100644 index 1c97523..0000000 --- a/jetson-agx-orin-devkit/Dockerfile +++ /dev/null @@ -1,91 +0,0 @@ -# AGX Orin, Orin NX and Orin Nano use the same T234 platform, therefore base images can be used -# interchangeably as long as nvidia.list contains the right apt repositoy -FROM balenalib/jetson-agx-orin-devkit-ubuntu:jammy-20240401 - -# Prevent apt-get prompting for input -ENV DEBIAN_FRONTEND noninteractive - -RUN echo "deb https://repo.download.nvidia.com/jetson/common r36.3 main" > /etc/apt/sources.list.d/nvidia.list \ - && echo "deb https://repo.download.nvidia.com/jetson/t234 r36.3 main" >> /etc/apt/sources.list.d/nvidia.list \ - && apt-key adv --fetch-key http://repo.download.nvidia.com/jetson/jetson-ota-public.asc \ - && mkdir -p /opt/nvidia/l4t-packages/ && touch /opt/nvidia/l4t-packages/.nv-l4t-disable-boot-fw-update-in-preinstall - -# Download and install BSP binaries for L4T 36.3 - Jetpack 6 -RUN \ - apt-get update && apt-get install -y wget tar lbzip2 binutils xz-utils zstd qemu-user-static cpio git && \ - cd /tmp/ && wget https://developer.nvidia.com/downloads/embedded/l4t/r36_release_v3.0/release/jetson_linux_r36.3.0_aarch64.tbz2 && \ - tar xf jetson_linux_r36.3.0_aarch64.tbz2 && \ - cd Linux_for_Tegra && \ - mkdir -p /tmp/Linux_for_Tegra/rootfs/boot/ && \ - mkdir -p /tmp/Linux_for_Tegra/rootfs/usr/bin && \ - mkdir -p /tmp/Linux_for_Tegra/rootfs/etc && touch /tmp/Linux_for_Tegra/rootfs/etc/resolv.conf && \ - sed -i 's/config.tbz2\"/config.tbz2\" --exclude=etc\/hosts --exclude=etc\/hostname/g' apply_binaries.sh && \ - sed -i 's/CheckPackage qemu-user-static/#CheckPackage qemu-user-static/g' tools/l4t_update_initrd.sh && \ - sed -i 's/trap CleanupVirEnv/#trap CleanupVirEnv/g' tools/l4t_update_initrd.sh&& \ - sed -i 's|cp /usr/bin/qemu-aarch64-static|#cp /usr/bin/qemu-aarch64-static|g' tools/l4t_update_initrd.sh && \ - sed -i 's|^UpdateInitrd|#UpdateInitrd|g' tools/l4t_update_initrd.sh && \ - sed -i 's|^UpdateBackToBaseInitrd|#UpdateBackToBaseInitrd|g' tools/l4t_update_initrd.sh && \ - sed -i 's|cp /etc/resolv.conf|#cp /etc/resolv.conf|g' tools/l4t_update_initrd.sh && \ - sed -i 's|mv "${LDK_ROOTFS_DIR}/etc/resolv.conf"|cp "${LDK_ROOTFS_DIR}/etc/resolv.conf"|g' tools/l4t_update_initrd.sh && \ - sed -i 's| PrepareVirEnv|#PrepareVirEnv|g' tools/l4t_update_initrd.sh && \ - sed -i 's/install --owner=root --group=root \"${QEMU_BIN}\" \"${L4T_ROOTFS_DIR}\/usr\/bin\/\"/#install --owner=root --group=root \"${QEMU_BIN}\" \"${L4T_ROOTFS_DIR}\/usr\/bin\/\"/g' nv_tegra/nv-apply-debs.sh && \ - sed -i 's/chroot . \// /g' nv_tegra/nv-apply-debs.sh && \ - cd /tmp/Linux_for_Tegra/ && ./apply_binaries.sh -r / --target-overlay && cd .. && \ - rm -rf Linux_for_Tegra && \ - echo "/usr/lib/aarch64-linux-gnu/tegra" > /etc/ld.so.conf.d/nvidia-tegra.conf && ldconfig - -# Install X and xfce -RUN \ - apt-get install -y --no-install-recommends \ - xserver-xorg-input-evdev \ - xinit \ - xfce4 \ - xfce4-terminal \ - x11-xserver-utils \ - dbus-x11 \ - xterm - -ENV LD_LIBRARY_PATH=/usr/lib/aarch64-linux-gnu/tegra -ENV UDEV=1 - -# Prevent screen from turning off -RUN echo "#!/bin/bash" > /etc/X11/xinit/xserverrc \ - && echo "" >> /etc/X11/xinit/xserverrc \ - && echo 'exec /usr/bin/X -s 0 dpms' >> /etc/X11/xinit/xserverrc && \ - echo 'modules=("nvidia_drm"); for module in "${modules[@]}"; do if lsmod | grep -q ${module} ; then echo "Found $module"; rmmod $module; fi; done; startxfce4;' > /opt/startxfce.sh - -## If any apt packages install mesa-egl, it will overwrite the tegra-egl -## symlink and ld path, so the following command will ensure tegra-egl remains -## available: -# RUN \ -# echo "/usr/lib/aarch64-linux-gnu/tegra\n/usr/lib/aarch64-linux-gnu/tegra-egl" \ -# > /etc/ld.so.conf.d/000-nvidia-tegra-egl.conf \ -# && ldconfig - -## Optional: Sample CUDA Clock sample run in webterminal: -## apt-get update && apt-get install -y -o Dpkg::Options::="--force-confdef" nvidia-l4t-cuda nvidia-cuda build-essential cuda-nvcc-12-2 && git clone https://github.com/NVIDIA/cuda-samples.git && cd cuda-samples/Samples/1_Utilities/deviceQuery && make && ./deviceQuery -## Example Output: -## -##./deviceQuery Starting... -## -## CUDA Device Query (Runtime API) version (CUDART static linking) -## -## Detected 1 CUDA Capable device(s) -## -## Device 0: "Orin" -## CUDA Driver Version / Runtime Version 12.2 / 12.2 -## CUDA Capability Major/Minor version number: 8.7 -## Total amount of global memory: 30701 MBytes (32191983616 bytes) -## (008) Multiprocessors, (128) CUDA Cores/MP: 1024 CUDA Cores -## GPU Max Clock rate: 1300 MHz (1.30 GHz) -## Memory Clock rate: 612 Mhz -## Memory Bus Width: 256-bit -## L2 Cache Size: 4194304 bytes -## ... -## deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 12.2, CUDA Runtime Version = 12.2, NumDevs = 1 -## Result = PASS - -# To start the XFCE desktop, the script called below does `rmmod nvidia_drm && rmmod nvidia_modeset && startxfce4` - -CMD ["/bin/bash", "/opt/startxfce.sh"] - diff --git a/jetson-nano/Dockerfile b/jetson-nano/Dockerfile index 26f1d23..2be795c 100644 --- a/jetson-nano/Dockerfile +++ b/jetson-nano/Dockerfile @@ -1,8 +1,35 @@ -FROM balenalib/jetson-nano-ubuntu:bionic +FROM ubuntu:bionic-20230530 # Prevent apt-get prompting for input ENV DEBIAN_FRONTEND noninteractive +# From balenalib base: +RUN apt-get update && apt-get install -y --no-install-recommends \ + less \ + kmod \ + nano \ + net-tools \ + sudo \ + ca-certificates \ + gnupg \ + dirmngr \ + inetutils-ping \ + netbase \ + curl \ + udev \ + ifupdown \ + i2c-tools \ + usbutils \ + $( \ + if apt-cache show 'iproute' 2>/dev/null | grep -q '^Version:'; then \ + echo 'iproute'; \ + else \ + echo 'iproute2'; \ + fi \ + ) \ + && rm -rf /var/lib/apt/lists/* \ + && c_rehash + # Update to 32.7 repository in case the base image is using 32.6 RUN sed -i 's/r32.6 main/r32.7 main/g' /etc/apt/sources.list.d/nvidia.list @@ -55,5 +82,7 @@ RUN echo "#!/bin/bash" > /etc/X11/xinit/xserverrc \ ## GPU Device 0: "Maxwell" with compute capability 5.3 ## Average clocks/block = 3294.203125 -# Start XFCE desktop -CMD ["startx"] +COPY entry.sh /usr/bin/entry.sh + +# Start entry script +CMD ["bash", "/usr/bin/entry.sh"] diff --git a/jetson-nano/entry.sh b/jetson-nano/entry.sh new file mode 100644 index 0000000..39a4fef --- /dev/null +++ b/jetson-nano/entry.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +# This command only works in privileged container +tmp_mount='/tmp/_balena' +mkdir -p "$tmp_mount" +if mount -t devtmpfs none "$tmp_mount" &> /dev/null; then + PRIVILEGED=true + umount "$tmp_mount" +else + PRIVILEGED=false +fi +rm -rf "$tmp_mount" + +function mount_dev() +{ + tmp_dir='/tmp/tmpmount' + mkdir -p "$tmp_dir" + mount -t devtmpfs none "$tmp_dir" + mkdir -p "$tmp_dir/shm" + mount --move /dev/shm "$tmp_dir/shm" + mkdir -p "$tmp_dir/mqueue" + mount --move /dev/mqueue "$tmp_dir/mqueue" + mkdir -p "$tmp_dir/pts" + mount --move /dev/pts "$tmp_dir/pts" + touch "$tmp_dir/console" + mount --move /dev/console "$tmp_dir/console" + umount /dev || true + mount --move "$tmp_dir" /dev + + # Since the devpts is mounted with -o newinstance by Docker, we need to make + # /dev/ptmx point to its ptmx. + # ref: https://www.kernel.org/doc/Documentation/filesystems/devpts.txt + ln -sf /dev/pts/ptmx /dev/ptmx + + # When using io.balena.features.sysfs the mount point will already exist + # we need to check the mountpoint first. + sysfs_dir='/sys/kernel/debug' + + if ! mountpoint -q "$sysfs_dir"; then + mount -t debugfs nodev "$sysfs_dir" + fi + +} + +function start_udev() +{ + if [ "$UDEV" == "on" ]; then + if $PRIVILEGED; then + mount_dev + if command -v udevd &>/dev/null; then + unshare --net udevd --daemon &> /dev/null + else + unshare --net /lib/systemd/systemd-udevd --daemon &> /dev/null + fi + udevadm trigger &> /dev/null + else + echo "Unable to start udev, container must be run in privileged mode to start udev!" + fi + fi +} + +function init() +{ + # echo error message, when executable file is passed but doesn't exist. + if [ -n "$1" ]; then + if CMD=$(command -v "$1" 2>/dev/null); then + shift + exec "$CMD" "$@" + else + echo "Command not found: $1" + exit 1 + fi + fi +} + +UDEV=$(echo "$UDEV" | awk '{print tolower($0)}') + +case "$UDEV" in + '1' | 'true') + UDEV='on' + ;; +esac + +start_udev +init "$@" +sleep 8 +startx diff --git a/jetson-orin/Dockerfile b/jetson-orin/Dockerfile index 2071f3a..0d096f5 100644 --- a/jetson-orin/Dockerfile +++ b/jetson-orin/Dockerfile @@ -1,6 +1,19 @@ # AGX Orin, Orin NX and Orin Nano use the same T234 platform, therefore base images can be used # interchangeably as long as nvidia.list contains the right apt repositoy -FROM balenalib/jetson-orin-nano-devkit-nvme-ubuntu:jammy-20240401 +FROM ubuntu:jammy-20250404 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + sudo \ + ca-certificates \ + findutils \ + gnupg \ + dirmngr \ + inetutils-ping \ + netbase \ + curl \ + udev \ + kmod \ + nano # Prevent apt-get prompting for input ENV DEBIAN_FRONTEND noninteractive @@ -46,13 +59,13 @@ RUN \ xterm ENV LD_LIBRARY_PATH=/usr/lib/aarch64-linux-gnu/tegra -ENV UDEV=1 # Prevent screen from turning off RUN echo "#!/bin/bash" > /etc/X11/xinit/xserverrc \ && echo "" >> /etc/X11/xinit/xserverrc \ - && echo 'exec /usr/bin/X -s 0 dpms' >> /etc/X11/xinit/xserverrc && \ - echo 'modules=("tegra_drm" "nvidia_drm" "nvidia_modeset"); for module in "${modules[@]}"; do if lsmod | grep -q ${module} ; then echo "Found $module"; rmmod $module; fi; done; startxfce4 & sleep 5; modprobe tegra_drm; modprobe nvidia_drm; while [ 1 ]; do sleep 10; done; ' > /opt/startxfce.sh + && echo 'exec /usr/bin/X -s 0 dpms' >> /etc/X11/xinit/xserverrc + + ## If any apt packages install mesa-egl, it will overwrite the tegra-egl ## symlink and ld path, so the following command will ensure tegra-egl remains @@ -110,5 +123,9 @@ RUN echo "#!/bin/bash" > /etc/X11/xinit/xserverrc \ ## deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 12.6, CUDA Runtime Version = 12.6, NumDevs = 1 ## Result = PASS -CMD ["/bin/bash", "/opt/startxfce.sh"] +COPY startxfce.sh /opt/startxfce.sh +RUN chmod +x /opt/startxfce.sh +COPY entry.sh /usr/bin/entry.sh +RUN chmod +x /usr/bin/entry.sh +CMD ["/bin/bash", "/usr/bin/entry.sh"] diff --git a/jetson-orin/entry.sh b/jetson-orin/entry.sh new file mode 100644 index 0000000..6721266 --- /dev/null +++ b/jetson-orin/entry.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +echo "Starting entry script." + +# This command only works in privileged container +tmp_mount='/tmp/_balena' +mkdir -p "$tmp_mount" +if mount -t devtmpfs none "$tmp_mount" &> /dev/null; then + PRIVILEGED=true + umount "$tmp_mount" +else + PRIVILEGED=false +fi +rm -rf "$tmp_mount" + +function mount_dev() +{ + tmp_dir='/tmp/tmpmount' + mkdir -p "$tmp_dir" + mount -t devtmpfs none "$tmp_dir" + mkdir -p "$tmp_dir/shm" + mount --move /dev/shm "$tmp_dir/shm" + mkdir -p "$tmp_dir/mqueue" + mount --move /dev/mqueue "$tmp_dir/mqueue" + mkdir -p "$tmp_dir/pts" + mount --move /dev/pts "$tmp_dir/pts" + touch "$tmp_dir/console" + mount --move /dev/console "$tmp_dir/console" + umount /dev || true + mount --move "$tmp_dir" /dev + + # Since the devpts is mounted with -o newinstance by Docker, we need to make + # /dev/ptmx point to its ptmx. + # ref: https://www.kernel.org/doc/Documentation/filesystems/devpts.txt + ln -sf /dev/pts/ptmx /dev/ptmx + + # When using io.balena.features.sysfs the mount point will already exist + # we need to check the mountpoint first. + sysfs_dir='/sys/kernel/debug' + + if ! mountpoint -q "$sysfs_dir"; then + mount -t debugfs nodev "$sysfs_dir" + fi + +} + +function start_udev() +{ + if [ "$UDEV" == "on" ]; then + if $PRIVILEGED; then + mount_dev + if command -v udevd &>/dev/null; then + unshare --net udevd --daemon &> /dev/null + else + unshare --net /lib/systemd/systemd-udevd --daemon &> /dev/null + fi + udevadm trigger &> /dev/null + else + echo "Unable to start udev, container must be run in privileged mode to start udev!" + fi + fi +} + +UDEV='on' + +echo "Starting UDEV..." +start_udev + +echo "Starting xfce script." +exec /opt/startxfce.sh diff --git a/jetson-orin/startxfce.sh b/jetson-orin/startxfce.sh new file mode 100644 index 0000000..2a36228 --- /dev/null +++ b/jetson-orin/startxfce.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +# Ensure plymouth exited so that it won't hold /dev/fb0 open and tegra_drm can be unloaded +DBUS_SYSTEM_BUS_ADDRESS=unix:path=/host/run/dbus/system_bus_socket \ + dbus-send \ + --system \ + --print-reply \ + --dest=org.freedesktop.systemd1 \ + /org/freedesktop/systemd1 \ + org.freedesktop.systemd1.Manager.StopUnit \ + string:plymouth-quit.service string:replace + +# Prevent "Server is already active for display 0" error, +# in case X was forcedly closed before +rm -rf /tmp/.X0-lock* || true + +# Prevent black screen with cursor only +rm -rf /root/.config/ || true + +modules=("tegra_drm" "nvidia_drm" "nvidia_modeset"); for module in "${modules[@]}"; +do + if lsmod | grep -q ${module} ; then + echo "Found $module"; rmmod $module; + fi; +done; + +startxfce4 & sleep 5; + +modprobe tegra_drm; +modprobe nvidia_drm; +while [ 1 ]; do + sleep 10; +done; diff --git a/jetson-tx2/Dockerfile b/jetson-tx2/Dockerfile index 0f3e597..90a7577 100644 --- a/jetson-tx2/Dockerfile +++ b/jetson-tx2/Dockerfile @@ -1,8 +1,40 @@ -FROM balenalib/jetson-tx2-ubuntu:bionic +FROM ubuntu:bionic-20230530 # Prevent apt-get prompting for input ENV DEBIAN_FRONTEND noninteractive +# From balenalib base: +RUN apt-get update && apt-get install -y --no-install-recommends \ + less \ + kmod \ + nano \ + net-tools \ + sudo \ + ca-certificates \ + gnupg \ + dirmngr \ + inetutils-ping \ + netbase \ + curl \ + udev \ + ifupdown \ + i2c-tools \ + usbutils \ + $( \ + if apt-cache show 'iproute' 2>/dev/null | grep -q '^Version:'; then \ + echo 'iproute'; \ + else \ + echo 'iproute2'; \ + fi \ + ) \ + && rm -rf /var/lib/apt/lists/* \ + && c_rehash + +RUN echo "deb https://repo.download.nvidia.com/jetson/common r32.7 main" >> /etc/apt/sources.list.d/nvidia.list \ + && echo "deb https://repo.download.nvidia.com/jetson/t186 r32.7 main" >> /etc/apt/sources.list.d/nvidia.list \ + && apt-key adv --fetch-key http://repo.download.nvidia.com/jetson/jetson-ota-public.asc \ + && mkdir -p /opt/nvidia/l4t-packages/ && touch /opt/nvidia/l4t-packages/.nv-l4t-disable-boot-fw-update-in-preinstall + RUN sed -i 's/r32.6 main/r32.7 main/g' /etc/apt/sources.list.d/nvidia.list # Download and install BSP binaries for L4T 32.7.2, as well as a few gstreamer packages for the purpose of running sample playback videos with gst-launch @@ -51,6 +83,7 @@ RUN echo "#!/bin/bash" > /etc/X11/xinit/xserverrc \ ## Optional: Sample CUDA Clock sample run in webterminal: ## apt-get install nvidia-l4t-cuda nvidia-cuda cuda-samples-10-2 && cd /usr/local/cuda-10.2/samples/0_Simple/clock/ && make && ./clock -# Start XFCE desktop -CMD ["startx"] +COPY entry.sh /usr/bin/entry.sh +# Start entry script +CMD ["bash", "/usr/bin/entry.sh"] diff --git a/jetson-tx2/entry.sh b/jetson-tx2/entry.sh new file mode 100644 index 0000000..39a4fef --- /dev/null +++ b/jetson-tx2/entry.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +# This command only works in privileged container +tmp_mount='/tmp/_balena' +mkdir -p "$tmp_mount" +if mount -t devtmpfs none "$tmp_mount" &> /dev/null; then + PRIVILEGED=true + umount "$tmp_mount" +else + PRIVILEGED=false +fi +rm -rf "$tmp_mount" + +function mount_dev() +{ + tmp_dir='/tmp/tmpmount' + mkdir -p "$tmp_dir" + mount -t devtmpfs none "$tmp_dir" + mkdir -p "$tmp_dir/shm" + mount --move /dev/shm "$tmp_dir/shm" + mkdir -p "$tmp_dir/mqueue" + mount --move /dev/mqueue "$tmp_dir/mqueue" + mkdir -p "$tmp_dir/pts" + mount --move /dev/pts "$tmp_dir/pts" + touch "$tmp_dir/console" + mount --move /dev/console "$tmp_dir/console" + umount /dev || true + mount --move "$tmp_dir" /dev + + # Since the devpts is mounted with -o newinstance by Docker, we need to make + # /dev/ptmx point to its ptmx. + # ref: https://www.kernel.org/doc/Documentation/filesystems/devpts.txt + ln -sf /dev/pts/ptmx /dev/ptmx + + # When using io.balena.features.sysfs the mount point will already exist + # we need to check the mountpoint first. + sysfs_dir='/sys/kernel/debug' + + if ! mountpoint -q "$sysfs_dir"; then + mount -t debugfs nodev "$sysfs_dir" + fi + +} + +function start_udev() +{ + if [ "$UDEV" == "on" ]; then + if $PRIVILEGED; then + mount_dev + if command -v udevd &>/dev/null; then + unshare --net udevd --daemon &> /dev/null + else + unshare --net /lib/systemd/systemd-udevd --daemon &> /dev/null + fi + udevadm trigger &> /dev/null + else + echo "Unable to start udev, container must be run in privileged mode to start udev!" + fi + fi +} + +function init() +{ + # echo error message, when executable file is passed but doesn't exist. + if [ -n "$1" ]; then + if CMD=$(command -v "$1" 2>/dev/null); then + shift + exec "$CMD" "$@" + else + echo "Command not found: $1" + exit 1 + fi + fi +} + +UDEV=$(echo "$UDEV" | awk '{print tolower($0)}') + +case "$UDEV" in + '1' | 'true') + UDEV='on' + ;; +esac + +start_udev +init "$@" +sleep 8 +startx diff --git a/jetson-xavier-agx/Dockerfile b/jetson-xavier-agx/Dockerfile index 229cd81..84c0be6 100644 --- a/jetson-xavier-agx/Dockerfile +++ b/jetson-xavier-agx/Dockerfile @@ -1,8 +1,35 @@ -FROM balenalib/jetson-xavier-ubuntu:bionic +FROM ubuntu:bionic-20230530 # Prevent apt-get prompting for input ENV DEBIAN_FRONTEND noninteractive +# From balenalib base: +RUN apt-get update && apt-get install -y --no-install-recommends \ + less \ + kmod \ + nano \ + net-tools \ + sudo \ + ca-certificates \ + gnupg \ + dirmngr \ + inetutils-ping \ + netbase \ + curl \ + udev \ + ifupdown \ + i2c-tools \ + usbutils \ + $( \ + if apt-cache show 'iproute' 2>/dev/null | grep -q '^Version:'; then \ + echo 'iproute'; \ + else \ + echo 'iproute2'; \ + fi \ + ) \ + && rm -rf /var/lib/apt/lists/* \ + && c_rehash + # Update to 32.5 repository, only if base image uses an older one: RUN sed -i 's/r32.6 main/r32.7 main/g' /etc/apt/sources.list.d/nvidia.list @@ -51,12 +78,9 @@ RUN echo "#!/bin/bash" > /etc/X11/xinit/xserverrc \ ## ## Optional: Sample CUDA Clock sample run in webterminal: ## apt-get install nvidia-l4t-cuda nvidia-cuda cuda-samples-10-2 && cd /usr/local/cuda-10.2/samples/0_Simple/clock/ && make && ./clock -## Output: -## CUDA Clock sample -## GPU Device 0: "Xavier" with compute capability 7.2 -## -## Average clocks/block = 3171.421875 -# Start XFCE desktop -CMD ["startx"] +COPY entry.sh /usr/bin/entry.sh + +# Start entry script +CMD ["bash", "/usr/bin/entry.sh"] diff --git a/jetson-xavier-agx/entry.sh b/jetson-xavier-agx/entry.sh new file mode 100644 index 0000000..39a4fef --- /dev/null +++ b/jetson-xavier-agx/entry.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +# This command only works in privileged container +tmp_mount='/tmp/_balena' +mkdir -p "$tmp_mount" +if mount -t devtmpfs none "$tmp_mount" &> /dev/null; then + PRIVILEGED=true + umount "$tmp_mount" +else + PRIVILEGED=false +fi +rm -rf "$tmp_mount" + +function mount_dev() +{ + tmp_dir='/tmp/tmpmount' + mkdir -p "$tmp_dir" + mount -t devtmpfs none "$tmp_dir" + mkdir -p "$tmp_dir/shm" + mount --move /dev/shm "$tmp_dir/shm" + mkdir -p "$tmp_dir/mqueue" + mount --move /dev/mqueue "$tmp_dir/mqueue" + mkdir -p "$tmp_dir/pts" + mount --move /dev/pts "$tmp_dir/pts" + touch "$tmp_dir/console" + mount --move /dev/console "$tmp_dir/console" + umount /dev || true + mount --move "$tmp_dir" /dev + + # Since the devpts is mounted with -o newinstance by Docker, we need to make + # /dev/ptmx point to its ptmx. + # ref: https://www.kernel.org/doc/Documentation/filesystems/devpts.txt + ln -sf /dev/pts/ptmx /dev/ptmx + + # When using io.balena.features.sysfs the mount point will already exist + # we need to check the mountpoint first. + sysfs_dir='/sys/kernel/debug' + + if ! mountpoint -q "$sysfs_dir"; then + mount -t debugfs nodev "$sysfs_dir" + fi + +} + +function start_udev() +{ + if [ "$UDEV" == "on" ]; then + if $PRIVILEGED; then + mount_dev + if command -v udevd &>/dev/null; then + unshare --net udevd --daemon &> /dev/null + else + unshare --net /lib/systemd/systemd-udevd --daemon &> /dev/null + fi + udevadm trigger &> /dev/null + else + echo "Unable to start udev, container must be run in privileged mode to start udev!" + fi + fi +} + +function init() +{ + # echo error message, when executable file is passed but doesn't exist. + if [ -n "$1" ]; then + if CMD=$(command -v "$1" 2>/dev/null); then + shift + exec "$CMD" "$@" + else + echo "Command not found: $1" + exit 1 + fi + fi +} + +UDEV=$(echo "$UDEV" | awk '{print tolower($0)}') + +case "$UDEV" in + '1' | 'true') + UDEV='on' + ;; +esac + +start_udev +init "$@" +sleep 8 +startx diff --git a/jetson-xavier-nx/Dockerfile b/jetson-xavier-nx/Dockerfile index 0c97c1f..adbe932 100644 --- a/jetson-xavier-nx/Dockerfile +++ b/jetson-xavier-nx/Dockerfile @@ -1,8 +1,40 @@ -FROM balenalib/jetson-xavier-nx-devkit-emmc-ubuntu:bionic +FROM ubuntu:bionic-20230530 # Prevent apt-get prompting for input ENV DEBIAN_FRONTEND noninteractive +# From balenalib base: +RUN apt-get update && apt-get install -y --no-install-recommends \ + less \ + kmod \ + nano \ + net-tools \ + sudo \ + ca-certificates \ + gnupg \ + dirmngr \ + inetutils-ping \ + netbase \ + curl \ + udev \ + ifupdown \ + i2c-tools \ + usbutils \ + $( \ + if apt-cache show 'iproute' 2>/dev/null | grep -q '^Version:'; then \ + echo 'iproute'; \ + else \ + echo 'iproute2'; \ + fi \ + ) \ + && rm -rf /var/lib/apt/lists/* \ + && c_rehash + +RUN echo "deb https://repo.download.nvidia.com/jetson/common r32.7 main" >> /etc/apt/sources.list.d/nvidia.list \ + && echo "deb https://repo.download.nvidia.com/jetson/t194 r32.7 main" >> /etc/apt/sources.list.d/nvidia.list \ + && apt-key adv --fetch-key http://repo.download.nvidia.com/jetson/jetson-ota-public.asc \ + && mkdir -p /opt/nvidia/l4t-packages/ && touch /opt/nvidia/l4t-packages/.nv-l4t-disable-boot-fw-update-in-preinstall + # Update to 32.6 repository in case the base image is using 32.5.1 RUN sed -i 's/r32.6 main/r32.7 main/g' /etc/apt/sources.list.d/nvidia.list @@ -52,6 +84,8 @@ RUN echo "#!/bin/bash" > /etc/X11/xinit/xserverrc \ ## Optional: Sample CUDA Clock sample run in webterminal: ## apt-get install nvidia-l4t-cuda nvidia-cuda cuda-samples-10-2 && cd /usr/local/cuda-10.2/samples/0_Simple/clock/ && make && ./clock -# Start XFCE desktop -CMD ["startx"] +COPY entry.sh /usr/bin/entry.sh + +# Start entry script +CMD ["bash", "/usr/bin/entry.sh"] diff --git a/jetson-xavier-nx/entry.sh b/jetson-xavier-nx/entry.sh new file mode 100644 index 0000000..39a4fef --- /dev/null +++ b/jetson-xavier-nx/entry.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +# This command only works in privileged container +tmp_mount='/tmp/_balena' +mkdir -p "$tmp_mount" +if mount -t devtmpfs none "$tmp_mount" &> /dev/null; then + PRIVILEGED=true + umount "$tmp_mount" +else + PRIVILEGED=false +fi +rm -rf "$tmp_mount" + +function mount_dev() +{ + tmp_dir='/tmp/tmpmount' + mkdir -p "$tmp_dir" + mount -t devtmpfs none "$tmp_dir" + mkdir -p "$tmp_dir/shm" + mount --move /dev/shm "$tmp_dir/shm" + mkdir -p "$tmp_dir/mqueue" + mount --move /dev/mqueue "$tmp_dir/mqueue" + mkdir -p "$tmp_dir/pts" + mount --move /dev/pts "$tmp_dir/pts" + touch "$tmp_dir/console" + mount --move /dev/console "$tmp_dir/console" + umount /dev || true + mount --move "$tmp_dir" /dev + + # Since the devpts is mounted with -o newinstance by Docker, we need to make + # /dev/ptmx point to its ptmx. + # ref: https://www.kernel.org/doc/Documentation/filesystems/devpts.txt + ln -sf /dev/pts/ptmx /dev/ptmx + + # When using io.balena.features.sysfs the mount point will already exist + # we need to check the mountpoint first. + sysfs_dir='/sys/kernel/debug' + + if ! mountpoint -q "$sysfs_dir"; then + mount -t debugfs nodev "$sysfs_dir" + fi + +} + +function start_udev() +{ + if [ "$UDEV" == "on" ]; then + if $PRIVILEGED; then + mount_dev + if command -v udevd &>/dev/null; then + unshare --net udevd --daemon &> /dev/null + else + unshare --net /lib/systemd/systemd-udevd --daemon &> /dev/null + fi + udevadm trigger &> /dev/null + else + echo "Unable to start udev, container must be run in privileged mode to start udev!" + fi + fi +} + +function init() +{ + # echo error message, when executable file is passed but doesn't exist. + if [ -n "$1" ]; then + if CMD=$(command -v "$1" 2>/dev/null); then + shift + exec "$CMD" "$@" + else + echo "Command not found: $1" + exit 1 + fi + fi +} + +UDEV=$(echo "$UDEV" | awk '{print tolower($0)}') + +case "$UDEV" in + '1' | 'true') + UDEV='on' + ;; +esac + +start_udev +init "$@" +sleep 8 +startx