Dev Containers + ROS2

Myron Rodrigues
5 min readAug 11, 2024

--

Development or Dev containers are simply put, docker containers that are configured to provide fully featured development environments. Here we will learn how to configure and build dev containers to create a fully featured ROS2 environment.

Why use Dev containers?

  • Isolation: Ensures that the ROS2 environment is consistent and isolated from the host system, avoiding conflicts with other installed software.
  • Reproducibility: Allows for the creation of a consistent development environment that can be shared among team members, ensuring everyone uses the same tools and dependencies.
  • Portability: Containers can be run on any system that supports Docker, making it easy to move between different machines and environments.
  • Simplified Dependency Management: All dependencies and tools required for ROS2 development are specified within the container, simplifying the setup process.
  • Version Control: Different versions of ROS2 or its dependencies can be managed easily by switching between different container images.

How to set up a Dev container?

There are 3 different types of files that are needed to set up a dev container.

  1. Dockerfile: Instructions to build the containers.
  2. docker-compose.yml: provide the configuration to build, run and combine the images built using Dockerfile.
  3. devcontainer.json: This file uses the docker-compose.yml files to build the services and also provides configuration for vs-code to work with the target service.

Lets set these up for a container layer structure as below.

Fig 1: Dev container architecture for a ROS2 computer vision dev environment.

1. Dockerfile

Multistage builds are used to separate container functionalities. Multistage builds are useful when extending the functionality of the container for different development or production environments.

The example here builds a computer vision stage over the base image and finally the development stage over it. This can be swapped to build other robotics functionalities related to the projects one works on. The file can be found here.

To keep dependencies clear from the builds they are listed in separate files with names apt-*-packages. The following Dockerfile command parses and installs the dependencies.

RUN apt-get update && \
apt-get install -y $(cut -d# -f1 </tmp/apt-base-packages | envsubst) \
&& rm -rf /var/lib/apt/lists/* /tmp/apt-base-packages

2. docker-compose.<type>.yml

These files are separated per type (base, cv, dev) to keep their functionality separate, which could be later combined in the devcontainer.json file.

To extend any service from a Dockerfile set the extends: field and specify the docker-compose.*.yml file under file: which has the service and the name of the service in that file as service: . These files can be found here.

3. devcontainer.json

We combine the services we built using docker-compose.yml file above to create the dev container.

name: is the name of the dev container.

dockerComposeFile: will be all the compose files used to build this dev container, they should appear in order they are used, i.e. base > cv > dev.

service: will be the service in which we will work in, dev obviously in our case.

workspaceFolder: will be the directory inside the dev container that will be opened in vs-code when the container is started.

For more info see this vs-code article.

Build

1. Exporting environment variables

Before building the containers a .env file must be configured. This contains the users UID, GID, name and group name which will be used to create a non-root user inside the dev container. This will also ensure the user has permissions to the mounted files and directories.

To generate the .env file in .devcontainer

# from ros2_dev_container
bash export_env.sh

2. Build the container in vs-code

Make sure you have the Dev Containers extension installed in vs-code.

Open ros2_dev_container directory in vs-code > press F1 > Dev Containers: Rebuild and Reopen in Container.

Usually once built vs-code will ask you to open this directory in container, which you can say yes. Or from command palette F1 and run Reopen in Container.

NOTE if the build fails, reopen in local folder option will show you logs. also see

3. For non vs-code users

The initial setup remains the same. Generate the .env file in .devcontainer.

# from ros2_dev_container
bash export_env.sh

3.a. Using docker-compose

  • To build or run the containers
# from ros2_dev_container
docker-compose -f .devcontainer/docker-compose.base.yml -f .devcontainer/docker-compose.cv.yml -f .devcontainer/docker-compose.dev.yml up -d
  • To get shell access into the container while its running. Get the name of the dev container from command above and run the following from another terminal.
docker exec -it <container_name> /bin/bash
  • To stop the containers.
# from ros2_dev_container
docker compose -f .devcontainer/docker-compose.base.yml -f .devcontainer/docker-compose.cv.yml -f .devcontainer/docker-compose.dev.yml down

3.b. Using devcontainers-cli

The cli version of the vs-code extension can also be used.

  • To build and start the container. This achieves the same as running Devcontainers: Rebuild from vs-code's command prompt.
# from ros2_dev_container
devcontainer up --remove-existing-container --workspace-folder .
  • To get shell access into the container while its running. This achieves the equivalent as running Devcontainers: Reopen in Container in vs-code.
# from ros2_dev_container
devcontainer exec --workspace-folder . bash
  • To stop the container
# To list all running containers
docker ps

# To stop the container by its ID
docker stop <container_id>

# To remove the container entirely
docker rm <container_id>

Examples

The dev containers we created above can be now used in various configurations as below and can be extended for complex production environments.

Production environments

The dev environment can simply be switched for a production container that usually will have dependency install instructions, launch files, config files and launch scripts.

Fig 2: Use in production environment

Other ROS2 environments

Developers can swap the computer vision container for example here the navigation container that builds over the same ROS2 base. This will ensure they start from the same base environments.

Fig 3: Navigation development environment

Combined production environment

Finally the computer vision and navigation environments can be combined as below and a final production environment can be built that combines the configurations and launch scripts of both the development environments.

Fig 4: Production environment with combined computer vision and navigation stacks

Conclusion

Leveraging Docker containers for ROS2 development offers significant advantages, including isolation, reproducibility, and simplified dependency management. By utilizing dev containers, developers can create consistent and portable development environments that are easy to share and maintain. Whether you choose to use vs-code’s dev containers or a more manual approach, this method will streamline your ROS2 development, making it more efficient and reliable.

For any issues and pull requests the code is here.

Thanks

Marcello for reviewing and editing the code.

--

--

Myron Rodrigues
Myron Rodrigues

Written by Myron Rodrigues

Robotics engineer specializing in computer vision and perception.