Create Overlay Docker Images
When working with MoveIt Studio, you will likely create new packages which may contain:
New Behaviors and Objectives
New robot configuration packages
Descriptions and drivers for a new robot
Novel algorithms currently not present in MoveIt Studio
For many of these applications, you can mount a user workspace directly into the MoveIt Studio Docker containers. However, there may be some use cases where this may not be sufficient, such as:
Your workspace requires additional binary packages, where
rosdep install
,apt-get install
,pip install
, etc. is needed to build the workspace.The hardware and/or algorithms you are working with require additional dependencies.
You want to install additional tools for debugging during development.
Creating a Release Overlay Container
You can create an overlay Docker image through the following steps:
Create a
Dockerfile
.Create a custom entrypoint to run at container startup.
Create
docker-compose.yaml
and.env
files to manage container configuration and startup.
Let’s first create the Dockerfile
.
The first layer will be called base
and do all the necessary setup.
This includes copying source code into the image, creating a new non-root user to that you have ownership of mounted files on the host, and installing any additional dependencies needed by your workspace.
# Extend the 2.6.0 release of MoveIt Studio
FROM picknikciuser/moveit-studio:2.6.0 as base
USER root
# Copy source code from the workspace's ROS 2 packages to a workspace inside the container
ARG USER_OVERLAY_WS=/opt/user_overlay_ws
ENV USER_OVERLAY_WS $USER_OVERLAY_WS
RUN mkdir -p ${USER_OVERLAY_WS}/src ${USER_OVERLAY_WS}/build ${USER_OVERLAY_WS}/install ${USER_OVERLAY_WS}/log
COPY ./src ${USER_OVERLAY_WS}/src
# Create a non-root user
ARG USERNAME
ARG USER_UID
ARG USER_GID
# Also mkdir with user permission directories which will be mounted later to avoid docker creating them as root
WORKDIR $USER_OVERLAY_WS
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
groupadd --gid $USER_GID ${USERNAME} && \
useradd --uid $USER_UID --gid $USER_GID --shell /bin/bash --create-home ${USERNAME} && \
apt-get update && \
apt-get install -q -y --no-install-recommends sudo && \
echo ${USERNAME} ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/${USERNAME} && \
chmod 0440 /etc/sudoers.d/${USERNAME} && \
mkdir -p \
/home/${USERNAME}/.ccache \
/home/${USERNAME}/.config \
/home/${USERNAME}/.ignition \
/home/${USERNAME}/.ros/log && \
chown -R $USER_UID:$USER_GID /home/${USERNAME} ${USER_OVERLAY_WS} /opt/overlay_ws/
# Install additional dependencies
# You can also add any necessary apt-get install, pip install, etc. commands at this point.
# NOTE: The /opt/overlay_ws folder contains MoveIt Studio binary packages and the source file.
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
. /opt/overlay_ws/install/setup.sh && \
apt-get update && \
rosdep install -q -y \
--from-paths src \
--ignore-src
# Remove .bashrc from parent image and create a new one
USER ${USERNAME}
RUN rm /home/${USERNAME}/.bashrc && touch /home/${USERNAME}/.bashrc
Next, we will create a new stage called user-overlay
which builds the source code for release and sets up an entrypoint (a script that executes at container startup).
FROM base as user-overlay
ARG USERNAME
USER ${USERNAME}
# Compile the workspace
# hadolint ignore=SC1091
RUN --mount=type=cache,target=/home/studio-user/.ccache \
. /opt/overlay_ws/install/setup.sh && \
colcon build
# Add the custom entrypoint
COPY ./entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
RUN echo "source /entrypoint.sh && set +e" >> ~/.bashrc
CMD ["/usr/bin/bash"]
The entrypoint script, named entrypoint.sh
, is copied in from your host system and should look as follows.
#!/bin/bash
set +e
# Source the MoveIt Studio binaries and your workspace
source "/opt/overlay_ws/install/setup.bash"
if [ -f "${USER_OVERLAY_WS}/install/local_setup.bash" ]; then
source "${USER_OVERLAY_WS}/install/local_setup.bash"
fi
# Set the location for custom Behavior package generation
export STUDIO_GENERATE_PACKAGE_OUTPUT_PATH="${USER_OVERLAY_WS}/src"
# Set the permissions for your non-root user at startup.
source /moveit_studio_utils/change_permissions.sh
# Set the DDS configuration for ROS 2 inter-process communication.
source /moveit_studio_utils/copy_dds_configs.sh
exec "$@"
Next, create a docker-compose.yaml
file which extends the docker-compose.yaml
file that was installed with MoveIt Studio.
The default location for the installed file is ${HOME}/moveit_studio/docker-compose.yaml
, but feel free to change this for your setup.
version: "3.9"
services:
# Sets common properties for other services. Should not be instantiated directly.
base:
# Extend the installed MoveIt Studio docker compose file.
# Change this to match your environment, if MoveIt Studio was installed to a different location.
extends:
file: ${HOME}/moveit_studio/docker-compose.yaml
service: base
image: moveit-studio-overlay
build:
context: .
target: user-overlay
args:
- USER_UID=${STUDIO_USER_UID:-1000}
- USER_GID=${STUDIO_USER_UID:-1000}
- USERNAME=${USERNAME:-studio-user}
Similarly, you can extend all the services from the base image as follows.
This can be directly copied from the docker-compose.yaml
that is installed with MoveIt Studio.
# Additional services
# Starts the MoveIt Studio Agent
agent_bridge:
extends: base
privileged: true
# Allow the user to use the host's network video4linux and usb_device devices.
# "c 81:* rmw": This rule specifies that the container has read, write, and mknod access (rmw) to all character devices (c) with a major number of 81 (video4linux).
# "c 189:* rmw": This rule gives the container read, write, and mknod access (rmw) to all character devices (c) with a major number of 189 (usb_device).
device_cgroup_rules:
- "c 81:* rmw"
- "c 189:* rmw"
depends_on:
rest_api:
condition: service_healthy
volumes:
# Allow the user to run graphical programs from within the docker container.
- /tmp/.X11-unix:/tmp/.X11-unix:ro
# Allow access to host hardware e.g. RealSense cameras
- /dev:/dev
deploy:
restart_policy:
condition: any
delay: 2s
command: agent_bridge.app
# Starts the REST API for the Web UI
rest_api:
extends: base
healthcheck:
test: "curl -f http://localhost:3200/objectives"
interval: 5s
timeout: 1m
command: rest_api.app
# Starts the robot drivers
drivers:
extends: base
privileged: true
# Ensures the drivers container has RT priority
ulimits:
rtprio: 99
devices:
- "/dev/ttyUSB0:/dev/ttyUSB0" # Allow access to the gripper.
command: robot.app
web_ui:
image: picknikciuser/moveit-studio-frontend:${STUDIO_DOCKER_TAG:-main}
ports:
- "80:80"
network_mode: host
# Starts RViz for visualization.
rviz:
extends: base
profiles:
- rviz
command: bash -c "ros2 launch moveit_studio_agent developer_rviz.launch.py"
# Starts MoveIt Setup Assistant for creating MoveIt configurations.
setup_assistant:
extends: base
profiles:
- setup_assistant
command: bash -c "ros2 launch moveit_setup_assistant setup_assistant.launch.py"
Finally, you can create a .env
file containing the necessary variables to use when launching MoveIt Studio.
For this example, you can include the following contents.
# Robot configuration package to launch
STUDIO_CONFIG_PACKAGE=picknik_ur_mock_hw_config
# MoveIt Studio version tag
# Be careful! Changing this without understanding the consequences may break your installation.
STUDIO_DOCKER_TAG=2.6.0
# Licensing -- enter your MoveIt Studio license below
STUDIO_LICENSE_KEY=
# User name and UID to use when building the container
# Ensure these settings match your host environment for mounted file permissions.
STUDIO_USERNAME=
STUDIO_USER_UID=
Now, you should be able to build and launch your MoveIt Studio overlay release image:
docker compose up
You can find a completed version of this example in the moveit_studio_ws repository.
Creating a Dev Container
With the release container workflow from the previous section, every time you change your source code you will need to rebuild the Docker image entirely for the changes to take effect when launching MoveIt Studio. One way to get around this is by making a developer container (or dev container) that mounts the source code and lets you build and run it repeatedly without restarting the container.
As an example, let us extend the moveit-studio-overlay
target in our Dockerfile
with a development target that adds a few extra packages for debugging.
FROM base as user-overlay-dev
USER root
# The location of the user's workspace inside the container
ARG USER_OVERLAY_WS=/opt/user_overlay_ws
ENV USER_OVERLAY_WS $USER_OVERLAY_WS
# Install any additional packages for development work
# hadolint ignore=DL3008
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && \
apt-get install -y --no-install-recommends \
less \
gdb \
nano
# Add the dev entrypoint
ARG USERNAME
USER ${USERNAME}
COPY ./entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
RUN echo "source /entrypoint.sh && set +e" >> ~/.bashrc
CMD ["/usr/bin/bash"]
You can then extend the docker-compose.yaml
file with a new service named dev
as follows:
# Developer specific configuration
dev:
extends: base
build:
target: user-overlay-dev
image: moveit-studio-overlay-dev
stdin_open: true
tty: true
privileged: true
volumes:
# Mount the source code, colcon generated artifacts, and ccache
- ./src/:/opt/user_overlay_ws/src:rw
- ./build/:/opt/user_overlay_ws/build:rw
- ./install/:/opt/user_overlay_ws/install:rw
- ./log/:/opt/user_overlay_ws/log:rw
- ./.ccache/:/home/${USERNAME:-studio-user}/.ccache:rw
# Allow access to host hardware e.g. RealSense cameras
- /dev:/dev
command: sleep infinity
# Making a separate profile prevents this service from being built when using `docker compose build`
# and launched when using `docker compose up`.
profiles: ["dev"]
Note that we mount several folders in addition to the src
folder of the workspace.
This ensures that artifacts generated by colcon build
persist between container instances.
Now, you should be able to build and launch your MoveIt Studio overlay dev container:
docker compose build dev
docker compose up dev
Once you have started the dev container, you can enter an interactive Bash session and launch one of the MoveIt Studio launch files directly. For example:
docker compose exec -it dev bash
Once inside the container, you can compile, run tests, or even launch different parts of the MoveIt Studio application.
colcon build
source install/setup.bash
ros2 launch moveit_studio_agent studio_agent.launch.py
Note
Using Docker containers for development is a common practice. Many IDEs, such as Visual Studio Code and PyCharm, have built-in support for developing with Docker containers. Once you have familiarized yourself with the steps above, we recommend setting up your favorite IDE(s) to help you develop new functionality for MoveIt Studio.