Docker images for the UTD RoboBoat 2026 competition cycle. Two images live here:
| Service / image | What it is | Needs an NVIDIA GPU? |
|---|---|---|
development (Docker/Dockerfile) |
ROS 2 Humble dev environment with the galaxsea_ws workspace (galaxsea + ROS-TCP-Endpoint) in /root/galaxsea_ws, plus rqt/rviz2. This is where you write and run code. |
No |
zed-sim (Docker/Dockerfile.zed) |
ZED SDK + zed-ros2-wrapper running against the virtual ZED 2i camera in the Unity simulator. |
Yes |
Important
The zed-sim image requires an NVIDIA GPU (plus the NVIDIA driver and the
NVIDIA Container Toolkit
on the host). The ZED SDK is CUDA-only; there is no CPU fallback, and it will not work inside a VM
or on a Mac. A workaround that does not use the ZED SDK is being worked on for laptops without a
GPU — until then, the development image works everywhere and you just won't have the
/zed/... topics locally.
- Docker with the Compose v2 plugin. Commands below use
docker compose(with a space); the olddocker-composebinary is not supported. - ~15 GB of free disk for the
developmentimage, ~25 GB more if you buildzed-sim. - For
zed-simonly: an NVIDIA GPU, the proprietary driver, and the NVIDIA Container Toolkit.
git clone https://github.com/RoboSub-UTD/roboboat-docker.git
cd roboboat-dockerThen follow the section for your operating system.
Tested on Ubuntu 22.04 / 24.04 with Docker Engine installed from Docker's own apt repository.
- Install Docker Engine + Compose plugin: https://docs.docker.com/engine/install/ubuntu/, and
add yourself to the
dockergroup (sudo usermod -aG docker $USER, then log out and back in). - Pull the prebuilt image (or build it, see Building):
docker compose pull development
- Start the container in the background and attach a shell to it:
docker compose up -d development docker compose attach development
- Inside the container, check that ROS 2 is healthy:
ros2 doctor
- Graphical tools (
rqt_graph,rviz2) open on your desktop through the X11 socket the compose file mounts. If a window does not appear, runxhost +local:dockerin a terminal on the host and try again.
If you have an NVIDIA GPU and want the simulated ZED camera, also install the NVIDIA Container Toolkit and see ZED camera in the Unity simulator.
Run Ubuntu in a virtual machine (VirtualBox, VMware, or Hyper-V) and do everything inside the VM.
Docker Desktop for Windows / WSL2 is not a supported path for this repo because of the host
networking and /dev access the containers need.
- Create an Ubuntu 22.04 or 24.04 VM. Give it as much RAM/CPU as you can spare and at least 60 GB of disk — the images are large.
- Inside the VM, follow the Ubuntu steps exactly as written.
- Graphical tools open inside the VM's desktop; if they don't, run
xhost +local:dockerin a terminal inside the VM.
Note
A VM does not get access to the host's NVIDIA GPU, so zed-sim cannot run in a VM even if
the Windows machine has an NVIDIA card. Use the development image only, and wait for the
no-SDK workaround for the camera.
Caution
Nobody on the team has verified these steps on a Mac yet. If you get it working (or hit a wall), please update this section.
Macs have no NVIDIA GPU, so only the development image applies. The image is built for
linux/amd64; on Apple Silicon Docker Desktop runs it under emulation, which works but is slow.
- Install Docker Desktop for Mac.
On Apple Silicon, open Settings → General and enable Use Rosetta for x86_64/amd64 emulation
on Apple Silicon — it is much faster than the default QEMU emulation. No extra
binfmtsetup is needed; Docker Desktop handleslinux/amd64images itself. - Install XQuartz for graphical tools:
brew install --cask xquartz, then log out and back in (XQuartz needs a fresh session to become your X server). Open XQuartz, go to Settings → Security, tick Allow connections from network clients, and restart XQuartz. - In a terminal, allow the container to talk to XQuartz and point
DISPLAYat it. Docker Desktop runs containers in a Linux VM, soDISPLAYmust go over the network to the Mac rather than through the/tmp/.X11-unixsocket:Do this in the same terminal you runxhost +localhost export DISPLAY=host.docker.internal:0docker composefrom, every session (or put theexportin your shell profile). - Pull, start and attach:
docker compose pull development docker compose up -d development docker compose attach development ros2 doctor
Known caveats: the compose file mounts /dev, uses network_mode: host and privileged — these
apply to Docker Desktop's Linux VM, not to macOS itself, so USB devices plugged into the Mac are not
visible in the container and ROS 2 discovery won't see nodes running natively on the Mac.
docker compose up -d development # start (or restart) the container in the background
docker compose attach development # open a shell in it (Ctrl-P Ctrl-Q detaches without stopping)docker compose attach connects to the container's one main shell, so a second attach just
mirrors the first. To get an extra, independent terminal in the same running container (e.g. one for
ros2 launch, another for ros2 topic echo), open a new terminal on the host and run:
docker exec -it roboboat-docker-development-1 /bin/bashYou'll land in the workspace with ROS 2 already sourced:
root@hostname:~/galaxsea_ws#
Repeat in as many terminals as you need; exit closes just that shell and leaves the container
running. (roboboat-docker-development-1 is the container name compose generates from the folder
name and service; if you cloned into a different folder, check docker ps for the actual name.)
The container is also a good target for VS Code's Dev Containers: Attach to Running Container.
/root/galaxsea_ws in the image is a fresh clone (with submodules) of
https://github.com/RoboSub-UTD/galaxsea_ws (main). That repo is the whole workspace; its src/ holds:
galaxsea: our boat codeROS-TCP-Endpoint: git submodule of https://github.com/Unity-Technologies/ROS-TCP-Endpoint (main-ros2), the ROS side of the Unity ↔ ROS bridge
The image ships the sources only; build them once inside the container:
cd /root/galaxsea_ws
rosdep update && rosdep install --from-paths src --ignore-src -r -y
colcon build --symlink-install
source install/setup.bash # new shells pick this up automaticallyAnything you change inside the container lives only in that container. docker compose up after
a rebuild, or docker compose down, throws it away — push your work to git.
The development image is built and pushed to Docker Hub by CI whenever Docker/Dockerfile
changes on main, so docker compose pull is usually enough. To build locally:
docker compose build development # ~10 min
docker compose build zed-sim # ~15 min, NVIDIA GPU machines onlyImportant
Requires an NVIDIA GPU, the NVIDIA driver and the NVIDIA Container Toolkit on a bare-metal Linux
host. It will not start on a machine without them (docker compose up zed-sim fails with an
nvidia runtime error). A ZED-SDK-free workaround for GPU-less laptops is in progress.
The Unity simulator (crane_sim) carries a virtual ZED 2i that streams into the real ZED SDK in
simulation mode. The zed-sim service runs zed-ros2-wrapper against that stream, so the usual
/zed/zed_node/... topics (rectified images, SDK stereo depth, point cloud, IMU) appear exactly as
on the boat. It is a separate image (Docker/Dockerfile.zed, ZED SDK 5.4.1 + wrapper v5.4.1 on
ROS 2 Humble); the development image does not contain any ZED software.
docker compose build zed-sim # once (~15 min, downloads the stereolabs/zed base image)
# start Unity, press Play (console: "ZED streamer ready ... port 30000"), then:
docker compose up zed-simTo check the depth is metric, tick Log ground truth depth on ZedSimCamera in Unity and read the
same pixels back from the SDK:
docker compose exec zed-sim python3 /root/depth_probe.pyIt prints the calibration the SDK is using (HD720: fx 529.8, principal point 640/360, no distortion, 120 mm baseline) and the depth at five pixels. Those should match Unity's logged ground-truth Z to a few centimetres; a constant ratio between them means the simulator's stereo rig and the SDK's calibration disagree. The script is bind-mounted, so editing it needs no rebuild.
docker compose: 'compose' is not a docker command— you have the old standalonedocker-compose. Install the Compose v2 plugin (docker-compose-pluginon Ubuntu).permission denied while trying to connect to the Docker daemon socket— add yourself to thedockergroup and log out/in.- No window appears for
rqt_graph/rviz2— runxhost +local:dockeron the host (or in the VM), then retry. On macOS make sure XQuartz is running andDISPLAYpoints at it. could not select device driver "nvidia"when startingzed-sim— the NVIDIA Container Toolkit isn't installed ornvidia-ctk runtime configure --runtime=dockerhasn't been run, or the machine simply has no NVIDIA GPU (see the note at the top).- Root-owned files appear in
.config/— tools in the container write their state through the/root/.configbind mount. They're gitignored;sudo rm -rf .config/<dir>if they bother you.