Dockerfile Plan
Reproducible Dockerfile for the isaac_ros_dev_container.
Context
Section titled “Context”The container (19.8 GB) was built interactively via docker exec + docker commit. No Dockerfile exists.
Target robot: Unitree G1 humanoid (Jetson Orin onboard). Container serves both simulation and real robot modes.
Decisions
Section titled “Decisions”| Decision | Choice |
|---|---|
| Base image | nvcr.io/nvidia/isaac/ros:noble-ros2_jazzy_d3e84470d576702a380478a513fb3fc6-amd64 (~19 GB, already pulled) |
| docker-compose.yml | Yes |
| Launch method | docker compose up -d with workspace-entrypoint.sh |
| Container name | isaac_ros_dev_container (required by ~/bin/ros2 wrapper and isaac-ros activate) |
| Unitree packages | NOT needed — G1 runs unitree_ros2 on its Orin, publishes standard ROS 2 topics |
isaac-ros activate compatibility: partial. Can set base_image_keys in ~/.config/isaac-ros-cli/config.yaml, but if the container is stopped/missing, it recreates from scratch. Always start with docker compose up -d first.
NVIDIA Reference Dockerfiles
Section titled “NVIDIA Reference Dockerfiles”At https://github.com/NVIDIA-ISAAC-ROS/isaac-ros-cli under docker/:
| File | What it does | Size |
|---|---|---|
Dockerfile.isaac_ros | Our base. Ubuntu Noble + apt repos (CUDA, Isaac ROS, Jetson, ROS2) + ros-jazzy-ros-base + entrypoint scripts | ~1.46 GB |
Dockerfile.noble | CUDA 13.0 dev + TensorRT + VPI + CV-CUDA + PyTorch + Triton + dev libs | ~15 GB+ |
Dockerfile.ros2_jazzy | Full ROS2 Jazzy: 50+ packages, nav2, rviz2, foxglove, custom OpenCV | ~3 GB+ |
Packages to Add on Top of Base
Section titled “Packages to Add on Top of Base”Base already includes foxglove-bridge, image-transport, nav2, rviz2, slam_toolbox, TensorRT, PyTorch, OpenCV, and CUDA dev tools. Only these need adding:
ros-jazzy-isaac-ros-apriltag # GPU AprilTag detectionros-jazzy-isaac-ros-visual-slam # cuVSLAM (visual SLAM)ros-jazzy-isaac-ros-nvblox # GPU 3D reconstructionros-jazzy-foxglove-compressed-video-transport # H.264 NVENC for Foxglove (community package, NOT in base)ros-jazzy-ffmpeg-encoder-decoder # ffmpeg with NVENCffmpeg # CLI toolCustom Configs
Section titled “Custom Configs”1. FastDDS no-SHM XML
Section titled “1. FastDDS no-SHM XML”Currently at /tmp/fastdds_no_shm.xml (ephemeral). Bake into /etc/fastdds_no_shm.xml.
<?xml version="1.0" encoding="UTF-8" ?><dds xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles"> <profiles> <transport_descriptors> <transport_descriptor> <transport_id>udp_transport</transport_id> <type>UDPv4</type> </transport_descriptor> </transport_descriptors> <participant profile_name="default_participant" is_default_profile="true"> <rtps> <userTransports> <transport_id>udp_transport</transport_id> </userTransports> <useBuiltinTransports>false</useBuiltinTransports> </rtps> </participant> </profiles></dds>2. admin user
Section titled “2. admin user”useradd -m -s /bin/bash -G sudo admin with UID 996 (matching host zeul). Required by isaac-ros activate.
3. FASTRTPS_DEFAULT_PROFILES_FILE env var
Section titled “3. FASTRTPS_DEFAULT_PROFILES_FILE env var”Do not use .bashrc — workspace-entrypoint.sh overwrites it. Use /etc/profile.d/fastdds-fix.sh pointing to /etc/fastdds_no_shm.xml.
4. Foxglove-bridge auto-start
Section titled “4. Foxglove-bridge auto-start”At /usr/local/bin/scripts/entrypoint_additions/50-foxglove-bridge.sh. Must set FASTRTPS_DEFAULT_PROFILES_FILE explicitly — entrypoint sources scripts, not login shells.
#!/bin/bashexport FASTRTPS_DEFAULT_PROFILES_FILE=/etc/fastdds_no_shm.xmlsource /opt/ros/jazzy/setup.bashros2 launch foxglove_bridge foxglove_bridge_launch.xml port:=8765 &5. H.264 NVENC republisher auto-start
Section titled “5. H.264 NVENC republisher auto-start”At /usr/local/bin/scripts/entrypoint_additions/60-h264-republisher.sh.
#!/bin/bashexport FASTRTPS_DEFAULT_PROFILES_FILE=/etc/fastdds_no_shm.xmlsource /opt/ros/jazzy/setup.bashros2 run image_transport republish raw foxglove --ros-args \ -r in:=/front_stereo_camera/left/image_rect_color \ -r out/foxglove:=/front_stereo_camera/left/compressed_video \ -p out.foxglove.encoder:=h264_nvenc \ -p out.foxglove.gop_size:=10 \ -p out.foxglove.bit_rate:=5000000 \ -p out.foxglove.qmax:=10 \ -p 'out.foxglove.encoder_av_options:=forced-idr:1,preset:p1,tune:ll' &AprilTag node launch with topic remapping
Section titled “AprilTag node launch with topic remapping”Default isaac_ros_apriltag subscribes to /image and /camera_info. Remap for carter warehouse:
ros2 launch isaac_ros_apriltag isaac_ros_apriltag.launch.py \ --ros-args \ -r image:=/front_stereo_camera/left/image_rect_color \ -r camera_info:=/front_stereo_camera/left/camera_infoConsider adding as an entrypoint addition script (e.g. 60-apriltag.sh).
NOT needed in Dockerfile (auto-generated or runtime junk)
Section titled “NOT needed in Dockerfile (auto-generated or runtime junk)”/etc/libibverbs.d/*,/etc/nvsciipc*,/etc/cufile.json— created by CUDA/NVIDIA package installs/etc/ghostscript/*,/etc/java/*,/etc/pulse/*— created by dependency installs/tmp/launch_params_*,/tmp/*.log— runtime temp files
Build Process
Section titled “Build Process”Step 1: Backups
Section titled “Step 1: Backups”# Tag old hand-built imagedocker tag isaac-ros-apriltag:latest isaac-ros-apriltag:oldFull base image already pulled.
Step 2: Create ~/workspaces/isaac_ros-dev/Dockerfile
Section titled “Step 2: Create ~/workspaces/isaac_ros-dev/Dockerfile”~40 lines: apt install Isaac ROS perception + foxglove H.264 transport + ffmpeg, create admin user, write FastDDS XML to /etc/, add /etc/profile.d/fastdds-fix.sh (NOT .bashrc — entrypoint overwrites it), create entrypoint addition scripts, set CMD/WORKDIR.
foxglove-bridge, image-transport, nav2, rviz2, TensorRT, PyTorch, OpenCV already in base — do NOT re-install.
Step 3: Create ~/workspaces/isaac_ros-dev/docker-compose.yml
Section titled “Step 3: Create ~/workspaces/isaac_ros-dev/docker-compose.yml”Container name isaac_ros_dev_container, runtime nvidia, host networking, ipc host, privileged, workspace bind mount.
Step 4: Build
Section titled “Step 4: Build”docker build -t isaac-ros-apriltag:latest ~/workspaces/isaac_ros-dev/Step 5: Sanity checks (throwaway containers)
Section titled “Step 5: Sanity checks (throwaway containers)”docker run --rm isaac-ros-apriltag:latest dpkg -l | grep isaac-ros-apriltagdocker run --rm isaac-ros-apriltag:latest id admindocker run --rm isaac-ros-apriltag:latest cat /etc/fastdds_no_shm.xmldocker run --rm isaac-ros-apriltag:latest cat /etc/profile.d/fastdds-fix.shdocker run --rm isaac-ros-apriltag:latest cat /usr/local/bin/scripts/entrypoint_additions/50-foxglove-bridge.shdocker run --rm isaac-ros-apriltag:latest cat /usr/local/bin/scripts/entrypoint_additions/60-h264-republisher.shStep 6: Swap container
Section titled “Step 6: Swap container”docker stop isaac_ros_dev_container && docker rm isaac_ros_dev_containerdocker compose -f ~/workspaces/isaac_ros-dev/docker-compose.yml up -dStep 7: Update ~/bin/ros2 wrapper
Section titled “Step 7: Update ~/bin/ros2 wrapper”Change FastDDS XML path from /tmp/ to /etc/.
Step 8: Live verification
Section titled “Step 8: Live verification”ros2 topic listfrom hostisaac-ros activateworks
Step 9: Cleanup (optional, after everything works)
Section titled “Step 9: Cleanup (optional, after everything works)”docker rmi isaac-ros-apriltag:old # Remove old 19GB hand-built imageStep 10: Update skill docs
Section titled “Step 10: Update skill docs”Files to Create/Modify
Section titled “Files to Create/Modify”| File | Action |
|---|---|
~/workspaces/isaac_ros-dev/Dockerfile | Create |
~/workspaces/isaac_ros-dev/docker-compose.yml | Create |
~/bin/ros2 | Update FastDDS XML path |
Verification Checklist
Section titled “Verification Checklist”docker buildcompletes without errorsdpkg -l | grep isaac-ros-apriltag— package presentid admin— UID 996cat /etc/fastdds_no_shm.xml— config presentFASTRTPS_DEFAULT_PROFILES_FILEset via/etc/profile.d/fastdds-fix.sh(NOT .bashrc)- Entrypoint addition scripts exist and are executable
docker compose up -dthenros2 topic listfrom host worksisaac-ros activatecan attach to running container (never use it to start one)- foxglove-bridge auto-starts on port 8765
- H.264 NVENC republisher auto-starts,
/front_stereo_camera/left/compressed_videotopic exists - Foxglove Studio connects to
ws://100.101.214.44:8765and shows camera feed /tag_detectionstopic publishes when AprilTag node is launched
Lessons Learned
Section titled “Lessons Learned”isaac-ros activateis destructive — if container is stopped, itdocker rms and recreates from base image. All customizations lost..bashrcgets overwritten — workspace-entrypoint.sh copies/etc/skel/.[^.]*over the user’s home dir. Use/etc/profile.d/for persistent env vars.- Entrypoint addition scripts must set their own env — they’re
sourced, not login shells, so/etc/profile.d/doesn’t apply. Each script must explicitlyexport FASTRTPS_DEFAULT_PROFILES_FILE=.... - Headless Isaac Sim needs explicit extension enable —
SimulationApp({"headless": True})does NOT auto-enableisaacsim.ros2.bridge. Callext_manager.set_extension_enabled_immediate("isaacsim.ros2.bridge", True)before loading scenes. - FastDDS SHM is the silent killer — topics discoverable across host/container but data doesn’t flow. Both the XML file AND env var must exist.
- H.265 NVENC doesn’t work with Foxglove — browser can’t decode keyframes. Use H.264 only.