ROS2 Docker (workshop 2)

Video of Workshop 2

The video of the first presentation of  Workshop 2 is here. The second presentation of Workshop 2 is here. It is mostly solving people's problems getting graphics to run in docker, but at the end we go through how to  configure the DISPLAY variable.

Content Outline

CLI Cheat Sheet

Docker commands run from the RPi or Ubuntu shell (i.e. not inside a container)

Terminator

The copy/shift & new tab/window keys are the same on a normal Ubuntu terminal.

Docker Concepts

A docker container is a virtual environment without the isolated kernel of a VM: the kernel is shared but the kernel provides isolation between containers and native apps. It's virtual in the sense that the apps run in an environment that looks like they have their own machine running its own OS, but they don't. Containers are a half-way house between apps running in a VM and apps running on the native OS. The container contains all libraries and executables above the kernel interface, so it is independent of the environment of the host running the container.

Images, containers: An image is like an executable file - a container gets instantiated (much as a process gets instantiated) and loaded with the image. The container runs the virtual environment. Different than a process, a container exists on disk and could have changes made to its files and they would persist for the life of the container. (We don't do that.) A container is the runnable form of an image. It provides a virtual environment which can run apps. In our way of using docker, we don't let containers persist (even though they could) - we delete them when they shut down. We use them as a short-term resource for running apps.  We choose to persist changes in the image, and rebuild the image when we need changes to the container. This keeps our configuration defined by the Dockerfile.

I provide a way to persist a container and relaunch it, which can be convenient for testing changes, but that's not the normal use case.

Images are built up in layers. In the Dockerfile we instruct the docker image builder to install apps and make other changes that will end up in the container. I own the content of the containers we'll use. I provide a template so that you can build on top of my containers and create your personally enhanced container. The active_docker function is useful to select which docker image you want to build, run or exec.

We configure the image to start a shell when a container is launched from the image. The terminal which launches the container gets a shell connection. Other terminals connect to a running container and get their own shell using docker exec. From their shells, each terminal can run different apps in the virtual environment (e.g. robot-app in one, ROS GUI in another, ROS bag recorder in another, and so on).

Hands-on

Install docker

In this segment we install the docker engine and utilities onto a system running an OS that isn't native Ubuntu 22.04

RPi running Raspberry Pi OS

Ubuntu PC or VM

Install docker on an Ubuntu system from these instructions: https://docs.docker.com/engine/install/ubuntu/ . Install docker on an RPi system from these instructions: https://docs.docker.com/engine/install/debian . Use the "Install using the apt repository" section of the instructions. Be sure to verify the installation by running the docker hello-world image per instructions

Configure .bashrc for running docker (RPi or PC)


# Aliases

#--------

# Docker functions

#

# if ~/.active_docker doesn't exist, create it & set active_docker to ros2_rpi

if [ ! -f ~/.active_docker ]

then

  echo "ros2_rpi" > .active_docker

fi

export ACTIVE_DOCKER=`cat ~/.active_docker`


active_docker () {

  if [ $# -eq 1 ]; then

    echo ${1} > ~/.active_docker

  fi

  export ACTIVE_DOCKER=`cat ~/.active_docker`

  echo $ACTIVE_DOCKER

}


# Docker aliases

export PATH_TO_ROS_DOCKERS=${HOME}'/ROS_dockers'


# CHANGE DISPLAY VARIABLE ON THE NEXT LINE AS NEEDED FOR YOUR SYSTEM

alias docker_build='cd ${PATH_TO_ROS_DOCKERS}/${ACTIVE_DOCKER} && docker build --build-arg CONFIGURED_USER=$USER --build-arg DISPLAY=:1 -t ${ACTIVE_DOCKER} .'

# docker run

alias dr='cd ${PATH_TO_ROS_DOCKERS}/${ACTIVE_DOCKER} && ./run_it.sh $@'

# docker exec

alias de='docker exec -it `docker ps -lq` bash'

# docker start last active container

alias dsl='docker start -ai `docker ps -lq`'



Configure github to allow your RPi to clone repos

In this segment we clone the ROS_dockers repo and build the ros2 docker images. Note: you must have a github account. <your_github_username> is your email address.


Select "Settings" under your account name

In the Settings menu, click on "SSH and GPG keys"

Click the "New SSH key" button to add your RPi ssh key.

Clone and build the ROS_dockers repo on RPi

Build the ROS dockers on PC

Precondition: You have previously accessed github.com from your PC and have your keys set up to download. If you haven't done that, you need to do a procedure similar to what's described above for RPi.


Launch ROS2  docker on RPi

In this segment we launch the ROS2 containers and verify correct operation of GUI and CLI and logins.

Launch ROS2 docker on PC

Test ROS2 docker on RPi and PC

Inspect the scripts

In this segment, we review how the system hangs together

Add a package to an image

In this exercise, we test adding a package to the ros2_rpi image, and when we're happy, we configure it into the my_rpi_mods Dockerfile, and build and test my_rpi_mods

Using a persistent container on RPi or PC

This technique for using docker launches a container from the ros:humble image, and persistes it, like a VM image persists. You can do manual modifications and they will persist, but BEWARE of the system prune command, which will blow away stopped containers. While this technique is comfortable for many, similar to a VM as it is, like installing in a VM it does not necessarily result in an easily reproducible image (because you make manual changes). Also, you run as root, which may have dire consequences if you typo. Also, it's a pretty minimal environment (e.g. ping is not installed, no GUI tools). OTOH it's as simple as it gets as a starting point.

Notice that you are root in a ros-humble docker container (shown by # prompt and ls /opt/ros)

Notice that the ros2 talker node is running.

You can re-launch the container as much as you want and it retains the changes made in it.