From 5729c8ef012ebb0396bdb2a484f400840003f7cd Mon Sep 17 00:00:00 2001 From: Pietro Pierpaoli Date: Fri, 22 Aug 2025 22:14:38 -0700 Subject: [PATCH 1/4] Sample project for creating humble/jazzy supervisor runtime dockers --- README.md | 43 ++++++++++++++++++++++ docker/Dockerfile | 79 ++++++++++++++++++++++++++++++++++++++++ docker/build_docker.bash | 36 ++++++++++++++++++ docker/entrypoint.sh | 18 +++++++++ docker/run_docker.bash | 45 +++++++++++++++++++++++ 5 files changed, 221 insertions(+) create mode 100755 docker/Dockerfile create mode 100755 docker/build_docker.bash create mode 100755 docker/entrypoint.sh create mode 100755 docker/run_docker.bash diff --git a/README.md b/README.md index 14a7c54..e702f6e 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,7 @@ This command will fully remove supervisor from your computer bash <(curl https://raw.githubusercontent.com/3LawsRobotics/3laws/master/uninstall.sh) ``` +<<<<<<< HEAD ## ROS2 install from source For distributions without available ROS2 packages (like debian), you can use the following scrip to build and install ROS2 in a way that is compatible with 3Laws Supervisor: [install_ros2.sh](https://raw.githubusercontent.com/3LawsRobotics/3laws/master/install_ros2.sh). @@ -137,6 +138,48 @@ You can then download and run the script: ```bash bash <(curl https://raw.githubusercontent.com/3LawsRobotics/3laws/master/install_ros2.sh) ``` +======= +## Docker runtime environment + +A sample Docker project is provided to assist users who prefer to install and execute Supervisor within a controlled environment. The project is not designed to meet any production-grade requirements, but rather to provide a starting point for further development. + +From the root directory, run `./docker/build_docker.bash ` to create the Docker image. Replace `` with either `humble` or `jazzy`. When the building is complete, run `./docker/run_docker.bash ` to start the container. + +The start script creates a local directory (default at `~/.3laws`) and mounted in the container at (default) `/home/3laws/.3laws`. The shared volume is used to store Supervisor configurations so that all savings and progresses persists across restarts of the container. + +In alternative to manually starting the container via the provided script, it is possible to call the script directly from a ROS 2 launch file: + +```python +import os + +from ament_index_python.packages import get_package_share_directory +from launch import LaunchDescription +from launch.actions import ExecuteProcess + + +def generate_launch_description(): + DOCKER_RUN_SCRIPT = os.path.join( + , + "run_docker.bash", + ) + + launchdesc = LaunchDescription( + [ + ExecuteProcess( + cmd=[DOCKER_RUN_SCRIPT], + shell=True, + output="screen", + name="lll_supervisor_docker", + ) + ] + ) + + return launchdesc + +``` + +IMPORTANT: When running the container for the first time, the Supervisor node will fail as no configuration file exists yet. Configure Supervisor through the Control Panel and restart the container. +>>>>>>> 30ee0c7 (Sample project for creating humble/jazzy supervisor runtime dockers) ## Repo maintainer diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100755 index 0000000..1ab098b --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,79 @@ +ARG ROS_DISTRO=humble +ARG BASE_IMAGE=ros:$ROS_DISTRO-ros-core +FROM $BASE_IMAGE + +## Sup options +ARG SUP_VERSION=1.4.0 +ARG ASSET_ID +ARG ASSET_NAME + +## User options +ARG USER_NAME=3laws +ARG LLL_USER_ID +ARG LLL_GROUP_ID +ARG LLL_DIALOUT_GID +ARG LLL_INPUT_GID + +## Install some packages +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + sudo \ + jq \ + software-properties-common \ + ros-$ROS_DISTRO-rosbridge-server + +# Install libstd++13 +RUN add-apt-repository ppa:ubuntu-toolchain-r/test && \ + apt-get update && \ + apt-get install -y --no-install-recommends \ + libstdc++-13-dev + +# To allow sourcing +RUN rm /bin/sh && ln -s /bin/bash /bin/sh + +## Create user +RUN userdel ubuntu || true +RUN groupadd -f --gid ${LLL_DIALOUT_GID} dialout +RUN groupadd -f --gid ${LLL_INPUT_GID} input +RUN groupadd -f --gid 1000 $USER_NAME-1000 +RUN groupadd -f --gid 1001 $USER_NAME-1001 +RUN groupadd -f --gid 2000 $USER_NAME-2000 +RUN groupadd -f --gid 999 $USER_NAME-999 +RUN groupadd -f --gid 118 $USER_NAME-118 +RUN groupadd -f --gid $LLL_GROUP_ID $USER_NAME +RUN useradd -ms /bin/bash $USER_NAME --uid $LLL_USER_ID -g $LLL_GROUP_ID -G 1000,1001,2000,999,118 +RUN echo "$USER_NAME:$USER_NAME" | chpasswd +RUN adduser $USER_NAME sudo + +# Remove need for password with sudo command +RUN echo $USER_NAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USER_NAME \ + && chmod 0440 /etc/sudoers.d/$USER_NAME + +# Add user to sudo and root groups +RUN usermod -aG sudo $USER_NAME +RUN usermod -aG root $USER_NAME + +# Switch to user +USER $USER_NAME +ENV HOME=/home/$USER_NAME +WORKDIR $HOME +RUN touch ".sudo_as_admin_successful" + + +## Get Supervisor +ENV GH_REPO="https://api.github.com/repos/3LawsRobotics/3laws" + +WORKDIR /tmp +ARG CURL_ARGS="-LJO#" +ARG GH_ASSET="$GH_REPO/releases/assets/$ASSET_ID" +RUN curl $CURL_ARGS -s -H 'Accept: application/octet-stream' "$GH_ASSET" + +## Install Supervisor +RUN sudo apt install -f ./"$ASSET_NAME" -y --no-install-recommends + +WORKDIR $HOME +RUN echo "source /opt/ros/$ROS_DISTRO/setup.bash" >> ~/.bashrc + +# Add entrypoint +COPY entrypoint.sh /home/$USER_NAME/entrypoint.sh +ENTRYPOINT ["/home/3laws/entrypoint.sh"] diff --git a/docker/build_docker.bash b/docker/build_docker.bash new file mode 100755 index 0000000..7541d49 --- /dev/null +++ b/docker/build_docker.bash @@ -0,0 +1,36 @@ +#!/bin/bash + +DOCKER_IMAGE_NAME="lll-supervisor-runtime" + +# Get ROS_DISTRO from first argument, error if not provided +if [ -z "$1" ]; then + echo "Usage: $0 . Specify jazzy|humble" + exit 1 +fi + +# Check if provided ROS_DISTRO is either "jazzy" or "humble" +if [ "$1" != "jazzy" ] && [ "$1" != "humble" ]; then + echo "Error - supported ROS_DISTRO values are: jazzy|humble" + exit 1 +fi +TAG=$1 + +GH_REPO="https://api.github.com/repos/3LawsRobotics/3laws/releases/latest" +PACKAGE_NAME="lll-supervisor-full-${TAG}" +REGEX_QUERY="${PACKAGE_NAME}_[0-9]\+\.[0-9]\+\.[0-9]\+-[0-9]\+_amd64" + +# Read asset tags. +RESPONSE=$(curl -s -H "application/vnd.github+json" $GH_REPO) +ASSET_NAME=$(echo "$RESPONSE" | grep -o "name.:.\+${REGEX_QUERY}.deb" | cut -d ":" -f2- | cut -d "\"" -f2-) +ASSET_ID=$(echo "$RESPONSE" | grep -C3 "name.:.\+$REGEX_QUERY" | grep -w id | tr : = | tr -cd '[[:alnum:]]=' | cut -d'=' -f2-) + +docker build --rm \ + --build-arg "LLL_USER_ID=$(id -u)" \ + --build-arg "LLL_GROUP_ID=$(id -g)" \ + --build-arg "LLL_DIALOUT_GID=$(getent group dialout | cut -d: -f3)" \ + --build-arg "LLL_INPUT_GID=$(getent group input | cut -d: -f3)" \ + --build-arg ROS_DISTRO=$TAG \ + --build-arg ASSET_ID=$ASSET_ID \ + --build-arg ASSET_NAME=$ASSET_NAME \ + -t $DOCKER_IMAGE_NAME:$TAG \ + -f "$(pwd)/Dockerfile" . diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh new file mode 100755 index 0000000..c3f51f3 --- /dev/null +++ b/docker/entrypoint.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +set -e # Exit immediately if a command exits with a non-zero status + +source /opt/ros/$ROS_DISTRO/setup.bash +ros2 launch rosbridge_server rosbridge_websocket_launch.xml port:=9091 & + +sleep 1 + +/opt/3laws/control_panel/control-panel-backend 8000 /opt/3laws/control_panel/build/ & +PID_CP=$! + +sleep 1 +ros2 launch lll_supervisor supervisor.launch.py + +wait $PID_CP + +echo "Control Panel backend exited, shutting down." diff --git a/docker/run_docker.bash b/docker/run_docker.bash new file mode 100755 index 0000000..35ddced --- /dev/null +++ b/docker/run_docker.bash @@ -0,0 +1,45 @@ +#!/bin/bash + +set -e # Exit on error, print commands, and treat unset variables as an error + +TAG="$1" +IMAGE_NAME="lll-supervisor-runtime" + +# Get all tags for the image +tags=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep "^${IMAGE_NAME}:" | cut -d: -f2) + +# Check if TAG exists in tags +if echo "$tags" | grep -q "^${TAG}$"; then + IMAGE_TAG=$TAG +else + echo "Selected tag '$TAG' not found. Available tags are:" + echo "$tags" + exit 1 +fi + + +LOCAL_USER_HOME=/home/$USER +LOCAL_LLL_CONFIG_DIR="$LOCAL_USER_HOME/.3laws" +DOCKER_HOME=/home/3laws +DOCKER_LLL_CONFIG_DIR="$DOCKER_HOME/.3laws" +IMAGE_NAME="lll-supervisor-runtime" + +# Check if Docker image exists +if ! docker image inspect $IMAGE_NAME:$IMAGE_TAG >/dev/null 2>&1; then + echo "Docker image $IMAGE_NAME:$IMAGE_TAG not found. Run build_docker.bash first to create image." + exit 1 +fi + +# Check if local ~/.3laws directory exists, if not create it +if [ ! -d "$LOCAL_LLL_CONFIG_DIR" ]; then + mkdir -p "$LOCAL_LLL_CONFIG_DIR" + chown -R "$(id -u)":"$(id -u)" "$LOCAL_LLL_CONFIG_DIR" + chmod -R u+rwX "$LOCAL_LLL_CONFIG_DIR" + echo "Created directory $LOCAL_LLL_CONFIG_DIR" +fi + +docker run --privileged --rm -it \ + --name lll-supervisor \ + --net=host \ + -v "$LOCAL_LLL_CONFIG_DIR":"$DOCKER_LLL_CONFIG_DIR" \ + $IMAGE_NAME:$IMAGE_TAG From aacca6f4249d30e7c7b81da934736a87bac84509 Mon Sep 17 00:00:00 2001 From: Pietro Pierpaoli Date: Mon, 15 Sep 2025 12:28:31 -0700 Subject: [PATCH 2/4] Refactors Docker setup for supervisor Simplified the Dockerfile and build process for the supervisor. --- docker/Dockerfile | 62 +++++----------------------------------- docker/build_docker.bash | 16 +++++------ docker/entrypoint.sh | 15 ++-------- docker/run_docker.bash | 20 ++++--------- 4 files changed, 22 insertions(+), 91 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 1ab098b..1c3f37f 100755 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -3,77 +3,29 @@ ARG BASE_IMAGE=ros:$ROS_DISTRO-ros-core FROM $BASE_IMAGE ## Sup options -ARG SUP_VERSION=1.4.0 ARG ASSET_ID ARG ASSET_NAME -## User options -ARG USER_NAME=3laws -ARG LLL_USER_ID -ARG LLL_GROUP_ID -ARG LLL_DIALOUT_GID -ARG LLL_INPUT_GID - ## Install some packages RUN apt-get update && \ apt-get install -y --no-install-recommends \ sudo \ - jq \ software-properties-common \ + screen \ + vim \ ros-$ROS_DISTRO-rosbridge-server -# Install libstd++13 -RUN add-apt-repository ppa:ubuntu-toolchain-r/test && \ - apt-get update && \ - apt-get install -y --no-install-recommends \ - libstdc++-13-dev - -# To allow sourcing -RUN rm /bin/sh && ln -s /bin/bash /bin/sh - -## Create user -RUN userdel ubuntu || true -RUN groupadd -f --gid ${LLL_DIALOUT_GID} dialout -RUN groupadd -f --gid ${LLL_INPUT_GID} input -RUN groupadd -f --gid 1000 $USER_NAME-1000 -RUN groupadd -f --gid 1001 $USER_NAME-1001 -RUN groupadd -f --gid 2000 $USER_NAME-2000 -RUN groupadd -f --gid 999 $USER_NAME-999 -RUN groupadd -f --gid 118 $USER_NAME-118 -RUN groupadd -f --gid $LLL_GROUP_ID $USER_NAME -RUN useradd -ms /bin/bash $USER_NAME --uid $LLL_USER_ID -g $LLL_GROUP_ID -G 1000,1001,2000,999,118 -RUN echo "$USER_NAME:$USER_NAME" | chpasswd -RUN adduser $USER_NAME sudo - -# Remove need for password with sudo command -RUN echo $USER_NAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USER_NAME \ - && chmod 0440 /etc/sudoers.d/$USER_NAME - -# Add user to sudo and root groups -RUN usermod -aG sudo $USER_NAME -RUN usermod -aG root $USER_NAME - -# Switch to user -USER $USER_NAME -ENV HOME=/home/$USER_NAME -WORKDIR $HOME -RUN touch ".sudo_as_admin_successful" - - ## Get Supervisor ENV GH_REPO="https://api.github.com/repos/3LawsRobotics/3laws" +## Install Supervisor WORKDIR /tmp ARG CURL_ARGS="-LJO#" ARG GH_ASSET="$GH_REPO/releases/assets/$ASSET_ID" RUN curl $CURL_ARGS -s -H 'Accept: application/octet-stream' "$GH_ASSET" - -## Install Supervisor RUN sudo apt install -f ./"$ASSET_NAME" -y --no-install-recommends -WORKDIR $HOME -RUN echo "source /opt/ros/$ROS_DISTRO/setup.bash" >> ~/.bashrc - -# Add entrypoint -COPY entrypoint.sh /home/$USER_NAME/entrypoint.sh -ENTRYPOINT ["/home/3laws/entrypoint.sh"] +## Add entrypoint +WORKDIR / +COPY entrypoint.sh /root/entrypoint.sh +ENTRYPOINT ["/root/entrypoint.sh"] diff --git a/docker/build_docker.bash b/docker/build_docker.bash index 7541d49..fe8bdb4 100755 --- a/docker/build_docker.bash +++ b/docker/build_docker.bash @@ -17,20 +17,18 @@ TAG=$1 GH_REPO="https://api.github.com/repos/3LawsRobotics/3laws/releases/latest" PACKAGE_NAME="lll-supervisor-full-${TAG}" -REGEX_QUERY="${PACKAGE_NAME}_[0-9]\+\.[0-9]\+\.[0-9]\+-[0-9]\+_amd64" +REGEX_QUERY="${PACKAGE_NAME}_[0-9]\+\.[0-9]\+\.[0-9]\+-[0-9]\+_amd64_ubuntu[0-9]\+.[0-9]\+" # Read asset tags. RESPONSE=$(curl -s -H "application/vnd.github+json" $GH_REPO) ASSET_NAME=$(echo "$RESPONSE" | grep -o "name.:.\+${REGEX_QUERY}.deb" | cut -d ":" -f2- | cut -d "\"" -f2-) ASSET_ID=$(echo "$RESPONSE" | grep -C3 "name.:.\+$REGEX_QUERY" | grep -w id | tr : = | tr -cd '[[:alnum:]]=' | cut -d'=' -f2-) +echo "Building Docker image $DOCKER_IMAGE_NAME:$TAG with asset $ASSET_NAME (id: $ASSET_ID)" + docker build --rm \ - --build-arg "LLL_USER_ID=$(id -u)" \ - --build-arg "LLL_GROUP_ID=$(id -g)" \ - --build-arg "LLL_DIALOUT_GID=$(getent group dialout | cut -d: -f3)" \ - --build-arg "LLL_INPUT_GID=$(getent group input | cut -d: -f3)" \ - --build-arg ROS_DISTRO=$TAG \ - --build-arg ASSET_ID=$ASSET_ID \ - --build-arg ASSET_NAME=$ASSET_NAME \ - -t $DOCKER_IMAGE_NAME:$TAG \ + --build-arg ROS_DISTRO="$TAG" \ + --build-arg ASSET_ID="$ASSET_ID" \ + --build-arg ASSET_NAME="$ASSET_NAME" \ + -t "$DOCKER_IMAGE_NAME:$TAG" \ -f "$(pwd)/Dockerfile" . diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index c3f51f3..64a9aa0 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -2,17 +2,8 @@ set -e # Exit immediately if a command exits with a non-zero status -source /opt/ros/$ROS_DISTRO/setup.bash -ros2 launch rosbridge_server rosbridge_websocket_launch.xml port:=9091 & +screen -dmS lll_rosbridge bash -lc "source /opt/ros/$ROS_DISTRO/setup.bash && exec ros2 launch rosbridge_server rosbridge_websocket_launch.xml port:=9091" -sleep 1 +screen -dmS lll_control_panel /opt/3laws/control_panel/control-panel-backend 8000 /opt/3laws/control_panel/build/ -/opt/3laws/control_panel/control-panel-backend 8000 /opt/3laws/control_panel/build/ & -PID_CP=$! - -sleep 1 -ros2 launch lll_supervisor supervisor.launch.py - -wait $PID_CP - -echo "Control Panel backend exited, shutting down." +source /opt/ros/humble/setup.bash && exec "$@" diff --git a/docker/run_docker.bash b/docker/run_docker.bash index 35ddced..7838964 100755 --- a/docker/run_docker.bash +++ b/docker/run_docker.bash @@ -17,11 +17,8 @@ else exit 1 fi - -LOCAL_USER_HOME=/home/$USER -LOCAL_LLL_CONFIG_DIR="$LOCAL_USER_HOME/.3laws" -DOCKER_HOME=/home/3laws -DOCKER_LLL_CONFIG_DIR="$DOCKER_HOME/.3laws" +DOCKER_HOME=/ +DOCKER_LLL_CONFIG_DIR="$DOCKER_HOME/.3laws/config" IMAGE_NAME="lll-supervisor-runtime" # Check if Docker image exists @@ -30,16 +27,9 @@ if ! docker image inspect $IMAGE_NAME:$IMAGE_TAG >/dev/null 2>&1; then exit 1 fi -# Check if local ~/.3laws directory exists, if not create it -if [ ! -d "$LOCAL_LLL_CONFIG_DIR" ]; then - mkdir -p "$LOCAL_LLL_CONFIG_DIR" - chown -R "$(id -u)":"$(id -u)" "$LOCAL_LLL_CONFIG_DIR" - chmod -R u+rwX "$LOCAL_LLL_CONFIG_DIR" - echo "Created directory $LOCAL_LLL_CONFIG_DIR" -fi - +docker volume create lll_supervisor_config docker run --privileged --rm -it \ --name lll-supervisor \ --net=host \ - -v "$LOCAL_LLL_CONFIG_DIR":"$DOCKER_LLL_CONFIG_DIR" \ - $IMAGE_NAME:$IMAGE_TAG + -v lll_supervisor_config:/$DOCKER_LLL_CONFIG_DIR/ \ + "$IMAGE_NAME":"$IMAGE_TAG" bash From d8587ccfe65d40c0772fc6ea6b418a2bd8834fe9 Mon Sep 17 00:00:00 2001 From: Pietro Pierpaoli Date: Wed, 22 Oct 2025 08:53:16 -0700 Subject: [PATCH 3/4] Adjusted docker instructions on README --- README.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e702f6e..7832846 100644 --- a/README.md +++ b/README.md @@ -143,9 +143,9 @@ bash <(curl https://raw.githubusercontent.com/3LawsRobotics/3laws/master/install A sample Docker project is provided to assist users who prefer to install and execute Supervisor within a controlled environment. The project is not designed to meet any production-grade requirements, but rather to provide a starting point for further development. -From the root directory, run `./docker/build_docker.bash ` to create the Docker image. Replace `` with either `humble` or `jazzy`. When the building is complete, run `./docker/run_docker.bash ` to start the container. +From the root directory of this project, run `./docker/build_docker.bash ` to create the runtime Docker image. Replace `` with either `humble` or `jazzy`. When building is complete, run `./docker/run_docker.bash ` to start the container. -The start script creates a local directory (default at `~/.3laws`) and mounted in the container at (default) `/home/3laws/.3laws`. The shared volume is used to store Supervisor configurations so that all savings and progresses persists across restarts of the container. +The start script creates a docker managed volume mounted at `~/.3laws`. The volume is used to store Supervisor configurations so that all savings and progresses persists across restarts of the container. In alternative to manually starting the container via the provided script, it is possible to call the script directly from a ROS 2 launch file: @@ -178,8 +178,17 @@ def generate_launch_description(): ``` +<<<<<<< HEAD IMPORTANT: When running the container for the first time, the Supervisor node will fail as no configuration file exists yet. Configure Supervisor through the Control Panel and restart the container. >>>>>>> 30ee0c7 (Sample project for creating humble/jazzy supervisor runtime dockers) +======= +When running the provided container, a `rosbridge_websocket` node and 3Laws Control Panel are started by the `entrypoint.sh` in the background inside dedicated `screen` sessions. At this point, you can follow the configuration steps described in the [Official Documentation](https://docs.3laws.io/en/latest/). + +Once the Supervisor configuration is complete, you can start the Supervisor from within the container via +```bash +ros2 launch lll_supervisor supervisor.launch.py +``` +>>>>>>> 9104773 (Adjusted docker instructions on README) ## Repo maintainer From 852e27261f4f41afa35fe120beec0df32389ed32 Mon Sep 17 00:00:00 2001 From: Pietro Pierpaoli Date: Wed, 22 Oct 2025 09:03:45 -0700 Subject: [PATCH 4/4] Fixed merged conflicts on README --- README.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7832846..c68f9b1 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,6 @@ This command will fully remove supervisor from your computer bash <(curl https://raw.githubusercontent.com/3LawsRobotics/3laws/master/uninstall.sh) ``` -<<<<<<< HEAD ## ROS2 install from source For distributions without available ROS2 packages (like debian), you can use the following scrip to build and install ROS2 in a way that is compatible with 3Laws Supervisor: [install_ros2.sh](https://raw.githubusercontent.com/3LawsRobotics/3laws/master/install_ros2.sh). @@ -138,7 +137,6 @@ You can then download and run the script: ```bash bash <(curl https://raw.githubusercontent.com/3LawsRobotics/3laws/master/install_ros2.sh) ``` -======= ## Docker runtime environment A sample Docker project is provided to assist users who prefer to install and execute Supervisor within a controlled environment. The project is not designed to meet any production-grade requirements, but rather to provide a starting point for further development. @@ -178,17 +176,15 @@ def generate_launch_description(): ``` -<<<<<<< HEAD + IMPORTANT: When running the container for the first time, the Supervisor node will fail as no configuration file exists yet. Configure Supervisor through the Control Panel and restart the container. ->>>>>>> 30ee0c7 (Sample project for creating humble/jazzy supervisor runtime dockers) -======= + When running the provided container, a `rosbridge_websocket` node and 3Laws Control Panel are started by the `entrypoint.sh` in the background inside dedicated `screen` sessions. At this point, you can follow the configuration steps described in the [Official Documentation](https://docs.3laws.io/en/latest/). Once the Supervisor configuration is complete, you can start the Supervisor from within the container via ```bash ros2 launch lll_supervisor supervisor.launch.py ``` ->>>>>>> 9104773 (Adjusted docker instructions on README) ## Repo maintainer