devcontainer for ROS2 project
Kohei Kawata
Posted on August 26, 2022
Summary
In this article, I want to share how to create your local development environment for ROS2 projects. Recent code development like the one with ROS2 framework has become very complex and heavily depending on OSS packages. VS Code devcontainer makes it much easier to create your local development environment.
TOC
Overview
devcontainer is one of Visual Studio Code Remote Development features that helps create local develop environment. Personally I love Windows OS and Visual Studio when developing .NET C# applications, but when in development with some other languages like Python, Typescript etc., VS Code devcontainer is really powerful. Here is my personal opinion of whe it is so useful.
Independent of your machine's operating system: According to statistica.com, Windows has around 75 percent of the global market share of operating system in 2022. Combined with WSL(Windows Subsystem for Linux) technology, VS Code devcontainer enables you to run Linux development environment in your Windows machine.
Package verion combinations: In general, you want to divide development environments depending on projects. For example, you can use
pyenv
,virtualenv
,conda
or whatever virtual environment you prefer for Python. However, when you want to combine the Python environment with other framework, for example ROS2, it is going to be more complex. VS Code devcontainer solves this problem by creating a just in time docker container for each development environment.No need to install all dependencies from scratch: To create your just in time development environment, you do not need to install all dependencies from scratch. You can utilize publicly available images from the well-known container registry. For example, I am using
ros:foxy-ros-base-focal
image for my ROS2 developenvironment - DockerfileDebugger: Visual Studio Code supports debuggers for different languages. For this exmaple - devcontainer.json, it uses
ms-python
VS Code extension with which you can run a Python debugger in your local machine.VS Code support and extensions: VS Code has built-in support and so many extensions for different languages. You can use those support even in the docker container development environment of devcontainer.
.devcontainer/devcontainer.json
The sample devcontainer.json looks like below.
-
dockerfile: This points to
Dockerfile
located in the same folder asdevcontainer.json
under.devcontainer
directory. -
workspaceFolder: The directory in the docker container where
.devcontainer
directory exists. - extensions: VS Code extensions you want to use in the docker contaienr development environment.
{
"name": "ROS devcontainer",
"dockerFile": "Dockerfile",
"workspaceFolder": "/workspaces/EdgeIntegrationTest/src/apps/FileGenerator",
"settings": {},
"extensions": [
"ms-python.python"
]
}
.devcontainer/Dockerfile
The sample Dockerfile under .devcontainer
directory looks like below.
-
FROM ros:foxy-ros-base-focal
: In this sample, it uses that ros image as the base image. It bases on ros:foxy-ros-core-focal, which bases on ubuntu:focal, which is the same asubuntu:20.04
. -
COPY requirements.txt ./
: Copyrequirements.txt
to/app
in the docker container so the docker container can runpip install
to set up necessary Python dependencies. -
RUN echo 'source /opt/ros/foxy/setup.bash' >> /root/.bashrc
: According to ROS2 documentation Configuring environment, in order to set up the docker container to access ROS2 commands, you need to source the set up files in the docker container -/opt/ros/foxy/setup.bash
. To avoid running the source command every time, it adds the source command to shell startup script.
FROM ros:foxy-ros-base-focal
SHELL ["/bin/bash", "-c"]
WORKDIR /app
COPY requirements.txt ./
RUN apt update && apt install -y \
python3-pip \
python3-colcon-common-extensions
RUN pip install -r requirements.txt
RUN echo 'source /opt/ros/foxy/setup.bash' >> /root/.bashrc
The location of setup.bash
file in the docker container
/opt
└── ros
└── foxy
├── _local_setup_util.py
├── bin
├── cmake
├── include
├── lib
├── local_setup.bash
├── local_setup.sh
├── local_setup.zsh
├── opt
├── setup.bash
├── setup.sh
├── setup.zsh
├── share
├── src
└── tools
Directory structure
How to run the docker container development environment
The step to open the development environment is like below.
- Go to your terminal and change your directory to where
.devcontainer
folder exists. - Run
code .
in your terminal, and you will see VS Code is coming up. - Go to
Open a Remote Window
and selectReopen in Container
, and you will see VS Code is reopened with the one running in the docker container.
Where is the project directory?
In this sample - .devcontainer, when the docker container VS Code is open, you will see your directory in the docker container is /workspaces/EdgeIntegrationTest/src/apps/FileGenerator
. You opened the devcontainer at FileGenerator
in your local machine directory. However, the docker container copied EdgeIntegrationTest
directory in your local machine to /workspaces
in the docker container.
EdgeIntegrationTest
└── src
└── apps
└── FileGenerator
├── .devcontainer
| ├── Dockerfile
| ├── devcontainer.json
| └── requirements.txt
├── Dockerfile
├── main.py
└── requirements.txt
Is this because your articulate "workspaceFolder": "/workspaces/EdgeIntegrationTest/src/apps/FileGenerator"
in devcontainer.json? No. If you change workspaceFolder
in devcontainer.json
to "workspaceFolder": "/workspaces/FileGenerator"
, you will see EdgeIntegrationTest
directory is copied under /workspaces
in the docker container and see the error below.
It seems like the VS Code Remote Development extension copies the directory where one .git
exists over your current directory in which you Reopen in Container
. I tried three experiments below.
Experiment 1
Reopen in Container at FileGenerator
in your local machine
C:.
└── FileGenerator
├── .devcontainer
| ├── Dockerfile
| ├── devcontainer.json
| └── requirements.txt
├── Dockerfile
├── main.py
└── requirements.txt
Your directory in the docker container
root@xxxxxxx:/workspaces/FileGenerator#
Experiment 2
Reopen in Container at FileGenerator
in your local machine
C:.
└── ProjectFolder1
├── .git
└── FileGenerator
├── .devcontainer
| ├── Dockerfile
| ├── devcontainer.json
| └── requirements.txt
├── Dockerfile
├── main.py
└── requirements.txt
Your directory in the docker container
root@xxxxxxx:/workspaces/ProjectFolder1/FileGenerator#
Experiment 3
Reopen in Container at FileGenerator
in your local machine
C:.
└── ProjectFolder2
├── .git
└── ProjectFolder1
├── .git
└── FileGenerator
├── .devcontainer
| ├── Dockerfile
| ├── devcontainer.json
| └── requirements.txt
├── Dockerfile
├── main.py
└── requirements.txt
Your directory in the docker container
root@xxxxxxx:/workspaces/ProjectFolder1/FileGenerator#
Posted on August 26, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.