@jrivero — this repository merges your docker/ from bluerobotics_models@jrivero/docker with the one on gz-maritime@lyrical. Both prototypes are in the history as their own commits with original authorship (cb608e3, 0297ee7), and 0bb379c is the merge.
Opening this rather than a PR because the repository was created with the merged state already on main. Review at your convenience — anything you disagree with is a normal PR from here.
Where your design was kept
Most of it, and verbatim where possible:
- The UID/GID user block. It is the strongest single piece of code in either prototype — renaming the base image's existing UID-1000 user rather than colliding with it is the trap most people hit on 26.04. Confirmed at build time:
usermod -l honu -d /home/honu -m -g 1000 ubuntu. Only USERNAME=ros → honu changed.
prepare_xauth() and the sudo-docker fallback from run.sh, verbatim.
entrypoint.sh, verbatim apart from WORKSPACE → DRYDOCK_WS. The conditional overlay sourcing is exactly right for a bind-mounted workspace that may not be built yet.
- BuildKit apt cache mounts,
rm -f docker-clean, SHELL -o pipefail, ARG DEBIAN_FRONTEND as ARG not ENV, OCI labels, the GL/Vulkan/X11 package list, QT_X11_NO_MITSHM.
- Your
README.md is the base for this one — the GPU truth table, the hybrid-laptop trap with the grep -c libGLX_nvidia /proc/<pid>/maps test, the nvidia-ctk runtime configure preflight, the touch /tmp/.docker.xauth warning, the GZ_PARTITION and PYTHONUNBUFFERED notes, and Troubleshooting are all yours.
- Your
x-env-nvidia comment about libglvnd silently resolving GLX to libGLX_mesa explains the failure mode better than anything else written on either side, so it moved across intact.
Three decisions
Reasoning for a few decision decisions associated with generalizing this from a single repo project to a four+ repo workspace.
1. The baked overlay (COPY . src/ && rosdep install && colcon build).
Structurally impossible here — the recipe lives in a separate repository from the source, so there is no . to copy. But even given a way around that, the motivating workflow for this repo is reviewing each other's PRs, and a baked overlay puts a image rebuild in front of every one of them. It also breaks a cross-repo edit touching gz_waves and bluerov2_gazebo in one sitting, which is normal here.
The image now contains no first-party source at all — apt packages only. Nothing is imported, resolved or built at image-build time. That is also what would let us publish the image publicly later without leaking anything.
Personally, I prefer keeping the automation limited to the docker side, so that the user is presented with an environment as similar as possible to that of the host. This also keeps instructions invariant to if someone is working in docker Especially at this early stage, I typically find that for debugging I have to undo the automation more often than not.
2. The six-service menu (sim / sim-headless / rviz / test / shell / sim-cpu / dev).
I think this is more automation for later. Also the NVIDIA overlay has to name every service, so adding a service means editing it — and adding a project means editing it again. There is now one service, dev, and named shortcuts are commands in projects/<name>/commands.sh.
sim-cpu is gone because the GPU auto-detection (from the gz-maritime side: requires both nvidia-smi -L and an nvidia runtime in docker info) already falls back to /dev/dri. True software rendering is LIBGL_ALWAYS_SOFTWARE=1 drydock sim.
3. The named ws-build / ws-install volumes.
They keep the host tree clean, which is genuinely nice. But they also hide log/latest_build/*/stdout_stderr.log, which is where you read compile errors, and they make install/ unavailable to host-side tooling. I suspect this was left over from CI workflows. This is more of a bare bones dev container with lots of transparency and introspection for developers.
What is new relative to both
cmake, build-essential, libeigen3-dev, libtbb-dev, libimath-dev — the EncinoWaves build dependencies. The gz-maritime prototype was missing all of them despite gz_waves_provider_fft doing find_package(EncinoWaves REQUIRED), so a colcon build in a fresh container could not have worked.
Related, and worth your eye since it touches your packaging work: encinowaves has no package.xml, so colcon silently skips it in a workspace. HonuRobotics/ehukai#19 adds one and HonuRobotics/gz-maritime#2 declares the dependency. The prebuilt libencinowaves-dev on packages.honurobotics.com stays documented as the alternative for consumers who never modify the library.
Verified
Ubuntu 26.04, Docker 29.5.2, Compose v5.1.4, RTX 2070 SUPER: image builds (4.62 GB), container runs as honu:1000 with HOME on the host home, glxinfo reports the discrete GPU rather than llvmpipe, all 7 workspace packages build in 35 s with EncinoWaves resolving from the workspace, gz sim -s runs 200 iterations headless.
@jrivero — this repository merges your
docker/frombluerobotics_models@jrivero/dockerwith the one ongz-maritime@lyrical. Both prototypes are in the history as their own commits with original authorship (cb608e3,0297ee7), and0bb379cis the merge.Opening this rather than a PR because the repository was created with the merged state already on
main. Review at your convenience — anything you disagree with is a normal PR from here.Where your design was kept
Most of it, and verbatim where possible:
usermod -l honu -d /home/honu -m -g 1000 ubuntu. OnlyUSERNAME=ros→honuchanged.prepare_xauth()and the sudo-docker fallback fromrun.sh, verbatim.entrypoint.sh, verbatim apart fromWORKSPACE→DRYDOCK_WS. The conditional overlay sourcing is exactly right for a bind-mounted workspace that may not be built yet.rm -f docker-clean,SHELL -o pipefail,ARG DEBIAN_FRONTENDas ARG not ENV, OCI labels, the GL/Vulkan/X11 package list,QT_X11_NO_MITSHM.README.mdis the base for this one — the GPU truth table, the hybrid-laptop trap with thegrep -c libGLX_nvidia /proc/<pid>/mapstest, thenvidia-ctk runtime configurepreflight, thetouch /tmp/.docker.xauthwarning, theGZ_PARTITIONandPYTHONUNBUFFEREDnotes, and Troubleshooting are all yours.x-env-nvidiacomment about libglvnd silently resolving GLX tolibGLX_mesaexplains the failure mode better than anything else written on either side, so it moved across intact.Three decisions
Reasoning for a few decision decisions associated with generalizing this from a single repo project to a four+ repo workspace.
1. The baked overlay (
COPY . src/ && rosdep install && colcon build).Structurally impossible here — the recipe lives in a separate repository from the source, so there is no
.to copy. But even given a way around that, the motivating workflow for this repo is reviewing each other's PRs, and a baked overlay puts a image rebuild in front of every one of them. It also breaks a cross-repo edit touchinggz_wavesandbluerov2_gazeboin one sitting, which is normal here.The image now contains no first-party source at all — apt packages only. Nothing is imported, resolved or built at image-build time. That is also what would let us publish the image publicly later without leaking anything.
Personally, I prefer keeping the automation limited to the docker side, so that the user is presented with an environment as similar as possible to that of the host. This also keeps instructions invariant to if someone is working in docker Especially at this early stage, I typically find that for debugging I have to undo the automation more often than not.
2. The six-service menu (
sim/sim-headless/rviz/test/shell/sim-cpu/dev).I think this is more automation for later. Also the NVIDIA overlay has to name every service, so adding a service means editing it — and adding a project means editing it again. There is now one service,
dev, and named shortcuts are commands inprojects/<name>/commands.sh.sim-cpuis gone because the GPU auto-detection (from the gz-maritime side: requires bothnvidia-smi -Land annvidiaruntime indocker info) already falls back to/dev/dri. True software rendering isLIBGL_ALWAYS_SOFTWARE=1 drydock sim.3. The named
ws-build/ws-installvolumes.They keep the host tree clean, which is genuinely nice. But they also hide
log/latest_build/*/stdout_stderr.log, which is where you read compile errors, and they makeinstall/unavailable to host-side tooling. I suspect this was left over from CI workflows. This is more of a bare bones dev container with lots of transparency and introspection for developers.What is new relative to both
cmake,build-essential,libeigen3-dev,libtbb-dev,libimath-dev— the EncinoWaves build dependencies. The gz-maritime prototype was missing all of them despitegz_waves_provider_fftdoingfind_package(EncinoWaves REQUIRED), so acolcon buildin a fresh container could not have worked.Related, and worth your eye since it touches your packaging work:
encinowaveshas nopackage.xml, so colcon silently skips it in a workspace. HonuRobotics/ehukai#19 adds one and HonuRobotics/gz-maritime#2 declares the dependency. The prebuiltlibencinowaves-devonpackages.honurobotics.comstays documented as the alternative for consumers who never modify the library.Verified
Ubuntu 26.04, Docker 29.5.2, Compose v5.1.4, RTX 2070 SUPER: image builds (4.62 GB), container runs as
honu:1000withHOMEon the host home,glxinforeports the discrete GPU rather than llvmpipe, all 7 workspace packages build in 35 s with EncinoWaves resolving from the workspace,gz sim -sruns 200 iterations headless.