Unverified Commit 1fb853cc authored by AutonomousHansen's avatar AutonomousHansen Committed by GitHub

Adds docker support for orbit (#40)

# Description

Adds a directory `docker` in the root of the repo, containing a
`Dockerfile`, `dockerfile-compose.yaml`, `.env`, and utility script
`container.sh` that wraps docker-compose CLI commands. The instructions
in the documentation specify the installation steps and how to get the
Isaac Sim docker image for completeness.

To run a container, the user needs to create NGC credentials via the
NVIDIA Developers program. After that they can run the script to launch
the container:

```bash
./docker/container.sh start
./docker/container.sh enter
```

Also added an argument `-o` or `--docker` to the `orbit.sh` that calls
the above script. The above then becomes:

```bash
./orbit.sh -o start 
./orbit.sh -o enter
```

Fixes #23 

## Type of change

- New feature (non-breaking change which adds functionality)

## Checklist

- [X] I have run the [`pre-commit` checks](https://pre-commit.com/) with
`./orbit.sh --format`
- [X] I have made corresponding changes to the documentation
- [X] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] I have updated the changelog and the corresponding version in the
extension's `config/extension.toml` file

---------
Co-authored-by: 's avatarMayank Mittal <mittalma@leggedrobotics.com>
parent cab9c56c
# ignore .git related folders
.git/
.github/
.gitignore
# ignore docs
docs/
# ignore logs
**/logs/
**/runs/
**/output/*
**/outputs/*
**/videos/*
*.tmp
# ignore docker
docker/
# ignore __pycache__
**/__pycache__/
**/*.egg-info/
# ignore isaac sim symlink
_isaac_sim?
# Accept the NVIDIA Omniverse EULA by default
ACCEPT_EULA=Y
# NVIDIA Isaac Sim version to use (e.g. 2022.2.1)
ISAACSIM_VERSION=2022.2.1
# Derived from the default path in the NVIDIA provided Isaac Sim container
DOCKER_ISAACSIM_PATH=/isaac-sim
# Docker user directory - by default this is the root user's home directory
DOCKER_USER_HOME=/root
# Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES, ETH Zurich, and University of Toronto
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
# Nvidia Dockerfiles:
# https://github.com/NVIDIA-Omniverse/IsaacSim-dockerfiles
# Base image
ARG ISAACSIM_VERSION
FROM nvcr.io/nvidia/isaac-sim:${ISAACSIM_VERSION}
# Adds labels to the Dockerfile
LABEL version="1.0"
LABEL description="Dockerfile for building and running the Orbit framework inside Isaac Sim container image."
# Arguments
# Path to Isaac Sim root folder
ARG ISAACSIM_PATH
# Set environment variables
ENV LANG=C.UTF-8
ENV DEBIAN_FRONTEND=noninteractive
ENV ORBIT_PATH=/workspace/orbit
# Install dependencies and remove cache
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
cmake \
git \
ncurses-term && \
apt -y autoremove && apt clean autoclean && \
rm -rf /var/lib/apt/lists/*
# FIXME: Only necessary for streaming until this fix is properly
# rolled out by NVIDIA after Isaac Sim2023.1 release
# Ref: https://forums.developer.nvidia.com/t/running-a-standalone-example-with-gui-in-docker-container/248147/3
RUN sed -i 's/\("omni.isaac.quadruped"\s=\s{}\)/"omni.isaac.quadruped" = {order = 10}/g' \
${ISAACSIM_PATH}/apps/omni.isaac.sim.python.kit
# Copy the orbit directory
COPY ../ ${ORBIT_PATH}
# Delete the logs directory
RUN rm -rf ${ORBIT_PATH}/logs
# Set up a symbolic link between the installed Isaac Sim root folder and _isaac_sim in the orbit directory
RUN ln -sf ${ISAACSIM_PATH} ${ORBIT_PATH}/_isaac_sim
# installing Orbit dependencies
RUN ${ORBIT_PATH}/orbit.sh --install --extra
# aliasing orbit.sh and python for convenience
RUN echo "alias orbit=${ORBIT_PATH}/orbit.sh" >> ${HOME}/.bashrc && \
echo "alias python=${ISAACSIM_PATH}/python.sh" >> ${HOME}/.bashrc && \
echo "alias python3=${ISAACSIM_PATH}/python.sh" >> ${HOME}/.bashrc && \
echo "alias pip='${ISAACSIM_PATH}/python.sh -m pip'" >> ${HOME}/.bashrc && \
echo "alias pip3='${ISAACSIM_PATH}/python.sh -m pip'" >> ${HOME}/.bashrc && \
echo "alias tensorboard='${ISAACSIM_PATH}/python.sh ${ISAACSIM_PATH}/tensorboard'" >> ${HOME}/.bashrc
# make working directory as the orbit directory
# this is the default directory when the container is run
WORKDIR ${ORBIT_PATH}
#!/bin/bash
#==
# Configurations
#==
# Exits if error occurs
set -e
# Set tab-spaces
tabs 4
# get script directory
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
#==
# Functions
#==
# print the usage description
print_help () {
echo -e "\nusage: $(basename "$0") [-h] [run] [start] [stop] -- Utility for handling docker in Orbit."
echo -e "\noptional arguments:"
echo -e "\t-h, --help Display the help content."
echo -e "\tstart Build the docker image and create the container in detached mode."
echo -e "\tenter Begin a new bash process within an existing orbit container."
echo -e "\tcopy Copy build and logs artifacts from the container to the host machine."
echo -e "\tstop Stop the docker container and remove it."
echo -e "\n" >&2
}
#==
# Main
#==
# check argument provided
if [ -z "$*" ]; then
echo "[Error] No arguments provided." >&2;
print_help
exit 1
fi
# check if docker is installed
if ! command -v docker &> /dev/null; then
echo "[Error] Docker is not installed! Please check the 'Docker Guide' for instruction." >&2;
exit 1
fi
# parse arguments
mode="$1"
# resolve mode
case $mode in
start)
echo "[INFO] Building the docker image and starting the container in the background..."
pushd ${SCRIPT_DIR} > /dev/null 2>&1
docker compose --file docker-compose.yaml up --detach --build --remove-orphans
popd > /dev/null 2>&1
;;
enter)
echo "[INFO] Entering the existing 'orbit' container in a bash session..."
pushd ${SCRIPT_DIR} > /dev/null 2>&1
docker exec --interactive --tty orbit bash
popd > /dev/null 2>&1
;;
copy)
# check if the container is running
if [ "$( docker container inspect -f '{{.State.Status}}' orbit 2> /dev/null)" != "running" ]; then
echo "[Error] The 'orbit' container is not running! It must be running to copy files from it." >&2;
exit 1
fi
echo "[INFO] Copying artifacts from the 'orbit' container..."
echo -e "\t - /workspace/orbit/logs -> ${SCRIPT_DIR}/artifacts/logs"
echo -e "\t - /workspace/orbit/docs/_build -> ${SCRIPT_DIR}/artifacts/docs/_build"
# enter the script directory
pushd ${SCRIPT_DIR} > /dev/null 2>&1
# We have to remove before copying because repeated copying without deletion
# causes strange errors such as nested _build directories
# warn the user
echo -e "[WARN] Removing the existing artifacts...\n"
rm -rf ./artifacts/logs ./artifacts/docs/_build
# create the directories
mkdir -p ./artifacts/docs
# copy the artifacts
docker cp orbit:/workspace/orbit/logs ./artifacts/logs
docker cp orbit:/workspace/orbit/docs/_build ./artifacts/docs/_build
echo -e "\n[INFO] Finished copying the artifacts from the container."
popd > /dev/null 2>&1
;;
stop)
echo "[INFO] Stopping the launched docker container..."
pushd ${SCRIPT_DIR} > /dev/null 2>&1
docker compose --file docker-compose.yaml down
popd > /dev/null 2>&1
;;
*)
echo "[Error] Invalid argument provided: $1"
print_help
exit 1
;;
esac
services:
# This service is used to build the Docker image
# The docker image is built from the root directory
orbit:
build:
context: ../
dockerfile: docker/Dockerfile
args:
- ISAACSIM_VERSION=${ISAACSIM_VERSION}
- ISAACSIM_PATH=${DOCKER_ISAACSIM_PATH}
image: orbit
container_name: orbit
env_file:
- .env
# We set DOCKER_ISAACSIM_PATH and then forward it to ISAACSIM_PATH within
# the container to avoid collision with pre-existing ISAACSIM_PATH env vars
# that could come from installing Orbit on the local machine, causing build errors
environment:
- ISAACSIM_PATH=${DOCKER_ISAACSIM_PATH}
- DISPLAY=${DISPLAY}
volumes:
# These volumes follow from this page
# https://docs.omniverse.nvidia.com/app_isaacsim/app_isaacsim/install_faq.html#save-isaac-sim-configs-on-local-disk
- type: volume
source: isaac-cache
target: ${DOCKER_ISAACSIM_PATH}/kit/cache/Kit
- type: volume
source: isaac-cache
target: ${DOCKER_USER_HOME}/.cache/ov
- type: volume
source: isaac-cache
target: ${DOCKER_USER_HOME}/.cache/pip
- type: volume
source: isaac-cache
target: ${DOCKER_USER_HOME}/.cache/nvidia/GLCache
- type: volume
source: isaac-cache
target: ${DOCKER_USER_HOME}/.nv/ComputeCache
- type: volume
source: isaac-logs
target: ${DOCKER_USER_HOME}/.nvidia-omniverse/logs
- type: volume
source: isaac-data
target: ${DOCKER_USER_HOME}/.local/share/ov/data
- type: volume
source: isaac-docs
target: ${DOCKER_USER_HOME}/Documents
# These volumes allow X11 Forwarding
- type: bind
source: /tmp/.X11-unix
target: /tmp/.X11-unix
- type: bind
source: ${HOME}/.Xauthority
target: ${DOCKER_USER_HOME}/.Xauthority
# This overlay allows changes on the local files to
# be reflected within the container immediately
- type: bind
source: ../source
target: /workspace/orbit/source
- type: bind
source: ../docs
target: /workspace/orbit/docs
# The effect of these volumes is twofold:
# 1. Prevent root-owned files from flooding the _build and logs dir
# on the host machine
# 2. Preserve the artifacts in persistent volumes for later copying
# to the host machine
- type: volume
source: orbit-docs
target: /workspace/orbit/docs/_build/
- type: volume
source: orbit-logs
target: /workspace/orbit/logs
network_mode: host
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [ gpu ]
# This is the entrypoint for the container
entrypoint: bash
stdin_open: true
tty: true
volumes:
# isaac-sim
isaac-cache:
isaac-logs:
isaac-data:
isaac-docs:
# orbit
orbit-docs:
orbit-logs:
......@@ -35,6 +35,7 @@ If you use ``orbit`` in your work, please cite the `paper <https://arxiv.org/abs
source/setup/installation
source/setup/developer
source/setup/docker
source/setup/sample
.. toctree::
......
Docker Guide
============
Docker is a tool that allows for the creation of containers, which are isolated environments that can
be used to run applications. They are useful for ensuring that an application can run on any machine
that has Docker installed, regardless of the host machine's operating system or installed libraries.
We include a Dockerfile and docker-compose.yaml file that can be used to build a Docker image that
contains Orbit and all of its dependencies. This image can then be used to run Orbit in a container.
The Dockerfile is based on the Isaac Sim image provided by NVIDIA, which includes the Omniverse
application launcher and the Isaac Sim application. The Dockerfile installs Orbit and its dependencies
on top of this image.
.. caution::
Due to the dependency on Isaac Sim docker image, by running this container you are implicitly
agreeing to the `NVIDIA Omniverse EULA`_. If you do not agree to the EULA, do not run this container.
Setup Instructions
------------------
.. note::
The following steps are taken from the NVIDIA Omniverse Isaac Sim documentation on `container installation`_.
They have been added here for the sake of completeness.
Docker and Docker Compose
~~~~~~~~~~~~~~~~~~~~~~~~~
We have tested the container using Docker Engine version 24.0.2 and Docker Compose version 2.18.1.
We recommend using these versions or newer.
* To install Docker, please follow the instructions for your operating system on the `Docker website`_.
* To install Docker Compose, please follow the instructions for your operating system on the `docker-compose`_ page.
* Follow the post-installation steps for Docker on the `post-installation steps`_ page. These steps allow you to run
Docker without using ``sudo``.
* To build and run GPU-accelerated containers, you also need install the `NVIDIA Container Toolkit`_.
Please follow the instructions on the `Container Toolkit website`_ for installation steps.
Obtaining the Isaac Sim Container
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Get access to the `Isaac Sim container`_ by joining the NVIDIA Developer Program credentials.
* Generate your `NGC API key`_ to access locked container images from NVIDIA GPU Cloud (NGC).
* This step requires you to create an NGC account if you do not already have one.
* You would also need to install the NGC CLI to perform operations from the command line.
* Once you have your generated API key and have installed the NGC CLI, you need to log in to NGC
from the terminal.
.. code:: bash
ngc config set
* Use the command line to pull the Isaac Sim container image from NGC.
.. code:: bash
docker login nvcr.io
* For the username, enter ``$oauthtoken`` exactly as shown. It is a special username that is used to
authenticate with NGC.
.. code:: text
Username: $oauthtoken
Password: <Your NGC API Key>
Directory Organization
----------------------
The root of the Orbit repository contains the ``docker`` directory that has various files and scripts
needed to run Orbit inside a Docker container. These are summarized below:
* ``Dockerfile``: Defines orbit image by overlaying Orbit dependencies onto the Isaac Sim Docker image.
* ``docker-compose.yaml``: Creates mounts to allow direct editing of Orbit code from the host machine that runs
the container along with X11 forwarding. It also creates several named volumes such as ``isaac-cache`` to store frequently
re-used resources compiled by Isaac Sim, such as shaders, and to retain logs, data, and documents.
* ``.env``: Stores environment variables required for the build process and the container itself.
* ``container.sh``: A script that wraps the ``docker-compose`` command to build the image and run the container.
Running the Container
---------------------
.. note::
The docker container copies all the files from the repository into the container at the
location ``/workspace/orbit``. This means that any changes made to the files in the container will not
be reflected in the repository.
To deal with this, we mount the following directories in the Orbit repository into the container
so that you can edit their files from the host machine:
* ``source``: This is the directory that contains the Orbit source code.
* ``docs``: This is the directory that contains the source code for Orbit documentation. This is overlaid except
for the ``_build`` subdirectory where build artifacts are stored.
The script ``container.sh`` wraps around three basic ``docker-compose`` commands:
1. ``start``: This builds the image and brings up the container in detached mode (i.e. in the background).
2. ``enter``: This begins a new bash process in an existing orbit container, and which can be exited
without bringing down the container.
3. ``copy``: This copies the ``logs`` and ``docs/_build`` artifacts, from the ``orbit-logs`` and ``orbit-docs``
volumes respectively, to the ``docker/artifacts`` directory. These artifacts persist between docker
container instances.
4. ``stop``: This brings down the container and removes it.
Following shows how to launch the container in a detached state and enter it:
.. code:: bash
# Launch the container in detached mode
./docker/container.sh start
# Enter the container
./docker/container.sh enter
To copy files from the container to the host machine, you can use the following command:
.. code:: bash
# Copy the file /workspace/orbit/logs to the current directory
docker cp orbit:/workspace/orbit/logs .
The script ``container.sh`` provides a wrapper around this command to copy the ``logs`` and ``docs/_build``
directories to the ``docker/artifacts`` directory. This is useful for copying the logs and documentation:
.. code:: bash
# Copy the logs and docs/_build directories to the docker/artifacts directory
./docker/container.sh copy
To stop the container, you can use the following command:
.. code:: bash
# stop the container
./docker/container.sh stop
Frequently Asked Questions
--------------------------
Python Interpreter
~~~~~~~~~~~~~~~~~~
The container uses the Python interpreter provided by Isaac Sim. This interpreter is located at
``/isaac-sim/python.sh``. We set aliases inside the container to make it easier to run the Python
interpreter. You can use the following commands to run the Python interpreter:
.. code:: bash
# Run the Python interpreter -> points to /isaac-sim/python.sh
python
Understanding the mounted volumes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The ``docker-compose.yaml`` file creates several named volumes that are mounted to the container.
These are summarized below:
* ``isaac-cache``: This volume is used to store frequently re-used resources compiled by Omniverse, such as shaders.
* ``isaac-logs``: This volume is used to store logs generated by Omniverse.
* ``isaac-data``: This volume is used to store data generated by Omniverse.
* ``isaac-docs``: This volume is used to store documents generated by Omniverse.
* ``orbit-docs``: This volume is used to store documentation of Orbit when built inside the container.
* ``orbit-logs``: This volume is used to store logs generated by Orbit workflows when ran inside the container.
To view the contents of these volumes, you can use the following command:
.. code:: bash
# list all volumes
docker volume ls
# inspect a specific volume, e.g. isaac-cache
docker volume inspect isaac-cache
Invalid mount config for type "bind"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you see the following error when building the container:
.. code:: text
⠋ Container orbit Creating 0.0s
Error response from daemon: invalid mount config for type "bind": bind source path does not exist: ${HOME}/.Xauthority
This means that the ``.Xauthority`` file is not present in the home directory of the host machine.
This file is required for X11 forwarding to work. To fix this, you can create an empty ``.Xauthority``
file in your home directory.
.. code:: bash
touch ${HOME}/.Xauthority
A similar error but requires a different fix:
.. code:: text
⠋ Container orbit Creating 0.0s
Error response from daemon: invalid mount config for type "bind": bind source path does not exist: /tmp/.X11-unix
This means that the folder/files are either not present or not accessible on the host machine. This usually happens
when you have multiple docker versions installed on your machine. To fix this, you can try the following:
* Remove all docker versions from your machine.
.. code:: bash
sudo apt remove docker*
sudo apt remove docker docker-engine docker.io containerd runc docker-desktop docker-compose-plugin
sudo snap remove docker
sudo apt clean autoclean && sudo apt autoremove --yes
* Install the latest version of docker based on the instructions in the setup section.
Known Issues
------------
WebRTC and WebSocket Streaming
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When streaming the GUI from Isaac Sim, there are `several options`_ available. There is a `known issue`_ when
attempting to use WebRTC streaming client on Google Chrome and Safari while running Isaac Sim inside a container.
To avoid this problem, we suggest using either the Native Streaming Client or WebSocket options, or using the
Mozilla Firefox browser on which WebRTC works.
.. _`NVIDIA Omniverse EULA`: https://docs.omniverse.nvidia.com/app_isaacsim/common/NVIDIA_Omniverse_License_Agreement.html
.. _`container installation`: https://docs.omniverse.nvidia.com/app_isaacsim/app_isaacsim/install_container.html
.. _`Docker website`: https://docs.docker.com/desktop/install/linux-install/
.. _`docker-compose`: https://docs.docker.com/compose/install/linux/#install-using-the-repository
.. _`NVIDIA Container Toolkit`: https://github.com/NVIDIA/nvidia-container-toolkit
.. _`Container Toolkit website`: https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html
.. _`post-installation steps`: https://docs.docker.com/engine/install/linux-postinstall/
.. _`Isaac Sim container`: https://catalog.ngc.nvidia.com/orgs/nvidia/containers/isaac-sim
.. _`NGC API key`: https://docs.nvidia.com/ngc/gpu-cloud/ngc-user-guide/index.html#generating-api-key
.. _several options: https://docs.omniverse.nvidia.com/app_isaacsim/app_isaacsim/manual_livestream_clients.html
.. _known issue: https://forums.developer.nvidia.com/t/unable-to-use-webrtc-when-i-run-runheadless-webrtc-sh-in-remote-headless-container/222916
......@@ -153,7 +153,7 @@ utilities to manage extensions:
./orbit.sh --help
usage: orbit.sh [-h] [-i] [-e] [-f] [-p] [-s] [-v] [-d] [-c] -- Utility to manage extensions in Orbit.
usage: orbit.sh [-h] [-i] [-e] [-f] [-p] [-s] [-o] [-v] [-d] [-c] -- Utility to manage extensions in Orbit.
optional arguments:
-h, --help Display the help content.
......@@ -162,6 +162,7 @@ utilities to manage extensions:
-f, --format Run pre-commit to format the code and check lints.
-p, --python Run the python executable (python.sh) provided by Isaac Sim.
-s, --sim Run the simulator executable (isaac-sim.sh) provided by Isaac Sim.
-o, --docker Run the docker container helper script (docker/container.sh).
-v, --vscode Generate the VSCode settings file from template.
-d, --docs Build the documentation from source using sphinx.
-c, --conda [NAME] Create the conda environment for Orbit. Default name is 'orbit'.
......
......@@ -177,7 +177,7 @@ update_vscode_settings() {
# print the usage description
print_help () {
echo -e "\nusage: $(basename "$0") [-h] [-i] [-e] [-f] [-p] [-s] [-v] [-d] [-c] -- Utility to manage extensions in Orbit."
echo -e "\nusage: $(basename "$0") [-h] [-i] [-e] [-f] [-p] [-s] [-o] [-v] [-d] [-c] -- Utility to manage extensions in Orbit."
echo -e "\noptional arguments:"
echo -e "\t-h, --help Display the help content."
echo -e "\t-i, --install Install the extensions inside Isaac Orbit."
......@@ -185,6 +185,7 @@ print_help () {
echo -e "\t-f, --format Run pre-commit to format the code and check lints."
echo -e "\t-p, --python Run the python executable (python.sh) provided by Isaac Sim."
echo -e "\t-s, --sim Run the simulator executable (isaac-sim.sh) provided by Isaac Sim."
echo -e "\t-o, --docker Run the docker container helper script (docker/container.sh)."
echo -e "\t-v, --vscode Generate the VSCode settings file from template."
echo -e "\t-d, --docs Build the documentation from source using sphinx."
echo -e "\t-c, --conda [NAME] Create the conda environment for Orbit. Default name is 'orbit'."
......@@ -214,6 +215,9 @@ while [[ $# -gt 0 ]]; do
# this does not check dependencies between extensions
export -f extract_python_exe
export -f install_orbit_extension
# downgrade setuptools to avoid issues with OpenAI Gym
# Check the `Known Issues` section in the documentation
$(extract_python_exe) -m pip install --upgrade setuptools==66
# source directory
find -L "${ORBIT_PATH}/source/extensions" -mindepth 1 -maxdepth 1 -type d -exec bash -c 'install_orbit_extension "{}"' \;
# unset local variables
......@@ -289,6 +293,15 @@ while [[ $# -gt 0 ]]; do
# exit neatly
break
;;
-o|--docker)
# run the docker container helper script
docker_script=${ORBIT_PATH}/docker/container.sh
echo "[INFO] Running docker utility script from: ${docker_script}"
shift # past argument
bash ${docker_script} $@
# exit neatly
break
;;
-v|--vscode)
# update the vscode settings
update_vscode_settings
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment