Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ROS2 Rust Development Environment and Supporting Scripts #435

Closed
wants to merge 9 commits into from
78 changes: 78 additions & 0 deletions .devcontainer/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
Development Container for ROS2 Rust
====================================

This repository includes a pre-configured development container setup, designed to facilitate working on ROS2 Rust projects. The setup is managed using Visual Studio Code's DevContainers feature.

.. contents:: Table of Contents
:depth: 3
:local:

File Description
----------------

The provided ``devcontainer.json`` file specifies the configuration for running a containerized development environment with the following features:

- **Image Configuration**: Uses the Docker image ``ros2_rust_dev:latest``.
- **Build Settings**:
- Context: Specifies the root directory of the project (``..``).
- Dockerfile: Uses the Dockerfile located at ``../docker/Dockerfile``.
- Build Args: Includes runtime environment variables such as ``XDG_RUNTIME_DIR``.
- **Workspace**:
- Mounts the folder ``/home/cuser/workspace`` as the development workspace.
- **Container Runtime**:
- Enables ``--network=host`` for network sharing.
- Grants privileged access using ``--privileged``.
- **Environment Variables**:
- ``DISPLAY`` and ``TERM`` are forwarded from the host to the container to support GUI applications and terminal colors.
- **User Settings**:
- The development container runs as the user ``cuser``.
- Configures the shell to use ``/bin/bash`` for a familiar and customizable command-line experience.

Setting Up and Running the DevContainer in VS Code
--------------------------------------------------

To use this development container in Visual Studio Code, follow these steps:

Prerequisites
~~~~~~~~~~~~~

1. **Install VS Code**: Download and install `Visual Studio Code <https://code.visualstudio.com/>`__.

2. **Install Required Extensions:**
- `Remote Containers <https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers>`__
3. **Install Docker:** Ensure Docker is installed and running on your system. You can download Docker from `here <https://www.docker.com/>`__.


Steps to Launch the DevContainer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1. **Clone the Repository**: Clone your project repository to your local machine.

.. code-block:: bash

$ git clone git@github.com:ros2-rust/ros2_rust.git
$ cd ros2_rust



2. **Open in VS Code**: Open the repository folder in VS Code.

.. code-block:: bash

$ code .

3. **Open the Command Palette**: Press ``Ctrl+Shift+P`` (Windows/Linux) or ``Cmd+Shift+P`` (macOS) to open the Command Palette.
4. **Reopen in Container**: Search for and select **"Dev Containers: Reopen in Container"**. VS Code will build and start the development container based on the configuration in ``devcontainer.json``.
5. **Start Coding**: Once the container is running, your workspace is ready for development. You can open terminals, run commands, and debug your ROS2 Rust projects seamlessly within the containerized environment.

Notes
~~~~~

- **Container Network**: The ``--network=host`` option is enabled to allow network sharing between the host and container.
- **Privilege**: The ``--privileged`` flag is enabled, which may be required for specific ROS2 features but should be used cautiously.
- If you encounter permission issues with X11, ensure the host system is configured to allow access in the vscode:

.. code-block:: bash

$ xhost local:root
$ code &
27 changes: 27 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@

{
"name": "ros2_rust_dev:latest",
"build": {
"context": "..",
"dockerfile": "../docker/Dockerfile",
"args": {
"XDG_RUNTIME_DIR": "${localEnv:XDG_RUNTIME_DIR}"
}
},
"workspaceFolder": "/home/cuser/workspace",
"runArgs": [
"--network=host",
"--privileged"
],
"containerEnv": {
"DISPLAY": "${localEnv:DISPLAY}",
"TERM": "xterm-256color"
},

"remoteUser": "cuser",
"containerEnv": {
// Convenience, for shell colors, aliases, etc
"SHELL": "/bin/bash"
}

}
26 changes: 23 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,23 @@
ARG ROS_DISTRO=humble
FROM ros:$ROS_DISTRO as base
FROM ros:$ROS_DISTRO AS base
ARG DEBIAN_FRONTEND=noninteractive

ARG CONTAINER_USER="cuser"
ARG USER_UID=1000
ARG USER_GID=$USER_UID

# Create a user in the container to operate as unprivileged
RUN groupadd --gid $USER_GID $CONTAINER_USER \
&& useradd --uid $USER_UID --gid $USER_GID -m $CONTAINER_USER \
&& mkdir -p /home/$CONTAINER_USER
RUN apt-get update \
&& apt-get install -y sudo \
&& rm -rf /var/lib/apt/lists/* \
&& echo $CONTAINER_USER ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$CONTAINER_USER \
&& chmod 0440 /etc/sudoers.d/$CONTAINER_USER

SHELL ["/bin/bash", "--login", "-c"]

# Install dependencies
RUN apt-get update && apt-get install -y \
curl \
Expand All @@ -11,14 +27,18 @@ RUN apt-get update && apt-get install -y \
python3-pip \
&& rm -rf /var/lib/apt/lists/*


# Install Rust
USER $CONTAINER_USER
WORKDIR /home/${CONTAINER_USER}
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --default-toolchain 1.75.0 -y
ENV PATH=/root/.cargo/bin:$PATH


RUN pip install --upgrade pytest

# Install the colcon-cargo and colcon-ros-cargo plugins
RUN pip install git+https://github.com/colcon/colcon-cargo.git git+https://github.com/colcon/colcon-ros-cargo.git

RUN mkdir -p /workspace && echo "Did you forget to mount the repository into the Docker container?" > /workspace/HELLO.txt
WORKDIR /workspace
RUN mkdir -p ~/workspace && echo "Did you forget to mount the repository into the Docker container?" > ~/workspace/HELLO.txt
WORKDIR /home/${CONTAINER_USER}/workspace
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ sudo apt install -y git libclang-dev python3-pip python3-vcstool # libclang-dev
pip install git+https://github.com/colcon/colcon-cargo.git
pip install git+https://github.com/colcon/colcon-ros-cargo.git

mkdir -p workspace/src && cd workspace
mkdir -p ~/workspace/src && cd ~/workspace
git clone https://github.com/ros2-rust/ros2_rust.git src/ros2_rust
vcs import src < src/ros2_rust/ros2_rust_humble.repos
. /opt/ros/humble/setup.sh
Expand Down
91 changes: 91 additions & 0 deletions docker/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
ROS2 Rust Docker Environment
=========================================================

This folder contains scripts to build, start, and interact with a Docker container for a ROS2 Rust environment.

.. contents:: Table of Contents
:depth: 3
:local:

Prerequisites
-------------

Ensure you have the following installed on your system:

- `Docker <https://docs.docker.com/engine/install/>`__
- Permissions to run Docker commands (sudo may be required on some systems).



Files in the Folder
-------------------

- `build.sh <./build.sh>`_: Builds the Docker image.
- `start.sh <./start.sh>`_: Starts the Docker container.
- `shell.sh <./shell.sh>`_: Accesses the running container


Steps to Use
------------

1. Build the Docker Image
~~~~~~~~~~~~~~~~~~~~~~~~~

Run the ``build.sh`` script to build the Docker image:

.. code-block:: bash

$ ./build.sh

This script:

- Builds a Docker image named ``ros2_rust:latest``.
- Uses ``BUILDKIT`` for efficient caching and builds.


2. Start the Docker Container
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Run the ``start.sh`` script to start the container:

.. code-block:: bash

$ ./start.sh

This script:

- Checks if a container based on the ros2_rust image exists and removes it if necessary.
- Starts a new container named ros2_rust with the following settings:
- **Interactive mode** (``-it``).
- **User ID Mapping**: Maps the current user (ID ``1000``) to the container user cuser.
- **Privileges**: Grants ``sudo`` group membership and system capabilities (e.g., sys_nice).
- **Networking**: Uses the host's network stack.
- **X11 Forwarding**: Allows graphical applications to be displayed on the host system.


3. Access the Running Container
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Run the ``shell.sh`` script to open an interactive shell in the running container:

.. code-block:: bash

$ ./shell.sh

This script:

- Opens a Bash shell as the user ``cuser``.
- Sets the working directory to ``/home/cuser/workspace``.


4. Install ros2 rust packages
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Follow the `README.md <../README.md>`_ file to install the overall packages needed to start working with ROS2 and Rust.


Notes
-----
- If you encounter permission issues with X11, ensure the host system is configured to allow access in each terminal:

.. code-block:: bash

$ xhost local:root
6 changes: 6 additions & 0 deletions docker/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
echo -e "Building ros2_rust:lastest image"
name=ros2_rust
DOCKER_BUILDKIT=1 \
docker build --pull --rm -f ../Dockerfile \
--build-arg BUILDKIT_INLINE_CACHE=1 \
--tag $name:latest .
2 changes: 2 additions & 0 deletions docker/shell.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
NAME=ros2_rust
exec docker exec -it $NAME sudo -u cuser -i /bin/bash -c "cd ~/workspace && exec /bin/bash"
29 changes: 29 additions & 0 deletions docker/start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
CUSER_ID="1000"
CONTAINER_USER="cuser"

IMAGE_NAME=ros2_rust

# Check if there are any containers created from the image
CONTAINERS=$(docker ps -a --filter "ancestor=$IMAGE_NAME" -q)

if [ -n "$CONTAINERS" ]; then
echo "Image has been used to start a container. Removing it."
docker stop $IMAGE_NAME
docker rm -f $IMAGE_NAME
else
echo "Image has not been started. Skipping removal."
fi

echo -e "Starting up ros2_rust container \n >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"

docker run -it --privileged \
--user=${CUSER_ID}:${CUSER_ID}\
--group-add sudo \
--env="DISPLAY" \
--env="QT_X11_NO_MITSHM=1" \
--workdir="/home/${CONTAINER_USER}/workspace" \
--volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
--net=host \
--cap-add=sys_nice \
--name=$IMAGE_NAME \
$IMAGE_NAME \
Loading