Running the Docker Container#

This page walks you through every step needed to log in to the PAL GitLab registry, pull the Kangaroo image, and launch it with full GPU and display support. It also explains how to keep your work safe across container restarts.

Prerequisites Checklist#

Before you begin, confirm that you have completed all the steps in Development on Docker:

  • Docker Engine installed and running (docker info returns no errors)

  • Your user is in the docker group (you can run docker ps without sudo)

  • NVIDIA drivers and NVIDIA Container Toolkit installed (if using GPU)

  • GitLab account with access to the Kangaroo Container Registry

  • pal_docker_utils set up (see below)


Step 1 โ€” Set Up pal_docker_utils#

PAL provides a helper script (pal_docker.sh) that wraps docker run with the correct flags for GPU acceleration, X11 display forwarding, and the exchange folder. You only need to do this once per machine.

Clone the repository and follow its setup instructions:

git clone https://github.com/pal-robotics/pal_docker_utils.git
cd pal_docker_utils

Then read and follow the README.md in that repository. The key steps are:

  1. Install nvidia-docker2 (if not done already).

  2. Restart the Docker daemon after configuration.

Important

If you skip the pal_docker_utils setup, you will not be able to run graphical applications such as Gazebo, RViz 2, or rqt from inside the container.


Step 2 โ€” Log In to the GitLab Container Registry#

You need to authenticate with the GitLab registry once per machine (credentials are stored in ~/.docker/config.json and reused on subsequent logins).

docker login registry.gitlab.com

When prompted, enter:

  • Username: your GitLab username

  • Password: your GitLab password or a personal access token with the read_registry scope (recommended over your account password)

A successful login prints:

Login Succeeded

Step 3 โ€” Find and Copy Your Image URL#

Go to your Kangaroo project on gitlab.com:

Left sidebar โ†’ Packages โ†’ Container Registry

Click the copy icon next to the image you want to use. The URL has the form:

registry.gitlab.com/<namespace>/kangaroo/<image-name>:<tag>

You will use this full URL in the next step. It is referred to as PATH_TO_YOUR_DOCKER_IMAGE in the commands below.



Step 5 โ€” Start the Container#

Use the pal_docker.sh script to launch a bash shell inside the container:

./pal_docker.sh -it PATH_TO_YOUR_DOCKER_IMAGE bash

The script passes the necessary flags for GPU access, X11 display forwarding, and mounts the exchange folder automatically. A prompt inside the container signals that it started successfully.

What pal_docker.sh does for you#

The script effectively runs something equivalent to:

docker run -it \
  --gpus all \
  --network host \
  --env DISPLAY=$DISPLAY \
  --volume /tmp/.X11-unix:/tmp/.X11-unix:rw \
  --volume ~/exchange:/home/user/exchange \
  PATH_TO_YOUR_DOCKER_IMAGE bash
  • --gpus all โ€” enables all NVIDIA GPUs inside the container

  • --network host โ€” shares the host network, which is needed for ROS 2 DDS communication

  • --env DISPLAY and --volume /tmp/.X11-unix โ€” forward the hostโ€™s X display so graphical apps work

  • --volume ~/exchange โ€” mounts the exchange folder for persistent file storage

Named containers โ€” reuse across sessions#

By default Docker assigns a random name to each container. Pass --name to give it a fixed name so you can stop and restart it across sessions without creating a new one each time:

./pal_docker.sh -it --name kangaroo-dev PATH_TO_YOUR_DOCKER_IMAGE bash

Once stopped, restart the same container (preserving any changes made inside it):

# Restart and reattach interactively in one command
docker start -ia kangaroo-dev

# Or restart it in the background, then exec into it
docker start kangaroo-dev
docker exec -it kangaroo-dev bash

Temporary containers โ€” --rm#

If you only need a throwaway session and do not want the container to persist after you exit, pass --rm:

./pal_docker.sh -it --rm PATH_TO_YOUR_DOCKER_IMAGE bash

The container is deleted automatically when the shell exits.

Dangling containers

Every docker run (or pal_docker.sh) call without --rm creates a new stopped container that remains on disk. Over time these accumulate and consume significant disk space. List them with docker ps -a and remove unused ones with docker container prune, or remove a specific one with docker rm <name-or-id>.


Step 6 โ€” Open Additional Terminals#

When the container is already running, open a new terminal session inside the same container (without starting a second container) using docker exec:

# Find your running container name or ID
docker ps

# Open a new bash session inside it
docker exec -it <container-name-or-id> bash

Using Terminator for a split-pane workflow#

Alternatively, launch Terminator from within the container session. This opens a Terminator window with X11 forwarding and lets you split it into multiple panes โ€” all already inside the container:

terminator -u &

The -u flag disables the D-Bus interface, which avoids startup warnings inside the container. Once the window opens, split it as needed:

  • Split horizontally: Ctrl+Shift+O

  • Split vertically: Ctrl+Shift+E

  • Close a pane: Ctrl+Shift+W

Each new pane is a fresh shell inside the same container โ€” useful for running a ROS 2 node in one pane, monitoring topics in another, and launching tools like rqt or plotjuggler in a third.


Persisting Your Work#

Critical โ€” Read Before Creating Any Files

Any file created inside the container that is not saved in the exchange folder will be permanently deleted when the container stops. The container filesystem is ephemeral by design.

The Exchange Folder#

The exchange folder is a bind-mounted directory shared between your host and the container:

Location

Path

On the host

~/exchange

Inside the container

/home/user/exchange

Always save work-in-progress, scripts, configuration files, ROS bags, and any other files you want to keep to this directory.

Typical Usage Pattern#

# Inside the container โ€” save your work to the exchange folder
cp my_config.yaml ~/exchange/
ros2 bag record -o ~/exchange/my_bag /joint_states

Troubleshooting#

Got permission denied while trying to connect to the Docker daemon#

Your user is not yet in the docker group. Run:

sudo usermod -aG docker $USER
newgrp docker

Then log out and back in.

Error response from daemon: could not select device driver "nvidia"#

The NVIDIA Container Toolkit is not installed or the Docker daemon was not restarted after installation. Follow the NVIDIA Container Toolkit guide and restart the daemon:

sudo systemctl restart docker

Graphical applications fail to open (cannot open display)#

X11 forwarding is not configured. Make sure:

  1. You are using pal_docker.sh and not a bare docker run command.

  2. You ran xhost +local:docker on the host before starting the container:

xhost +local:docker

docker login fails with unauthorized#

Check that your GitLab username is correct and that you are using a personal access token with read_registry scope rather than your account password (especially if you have two-factor authentication enabled on GitLab).