Running an example with Docker#
From the root of the Isaac Lab repository, the docker
directory contains all the Docker relevant files. These include the three files
(Dockerfile, docker-compose.yaml, .env) which are used by Docker, and an additional script that we use to interface with them,
container.py.
In this tutorial, we will learn how to use the Isaac Lab Docker container for development. For a detailed description of the Docker setup, including installation and obtaining access to an Isaac Sim image, please reference the Docker Guide. For a description of Docker in general, please refer to their official documentation.
Building the Container#
To build the Isaac Lab container from the root of the Isaac Lab repository, we will run the following:
python docker/container.py start
The terminal will first pull the base IsaacSim image, build the Isaac Lab image’s additional layers on top of it, and run the Isaac Lab container.
This should take several minutes upon the first build but will be shorter in subsequent runs as Docker’s caching prevents repeated work.
If we run the command docker container ls
on the terminal, the output will list the containers that are running on the system. If
everything has been set up correctly, a container with the NAME
isaac-lab-base should appear, similar to below:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
483d1d5e2def isaac-lab-base "bash" 30 seconds ago Up 30 seconds isaac-lab-base
Once the container is up and running, we can enter it from our terminal.
python docker/container.py enter
On entering the Isaac Lab container, we are in the terminal as the superuser, root
. This environment contains a copy of the
Isaac Lab repository, but also has access to the directories and libraries of Isaac Sim. We can run experiments from this environment
using a few convenient aliases that have been put into the root
.bashrc. For instance, we have made the isaaclab.sh script
usable from anywhere by typing its alias isaaclab
.
Additionally in the container, we have bind mounted the IsaacLab/source
directory from the
host machine. This means that if we modify files under this directory from an editor on the host machine, the changes are
reflected immediately within the container without requiring us to rebuild the Docker image.
We will now run a sample script from within the container to demonstrate how to extract artifacts from the Isaac Lab Docker container.
The Code#
The tutorial corresponds to the log_time.py
script in the IsaacLab/source/standalone/tutorials/00_sim
directory.
Code for log_time.py
1# Copyright (c) 2022-2024, The Isaac Lab Project Developers.
2# All rights reserved.
3#
4# SPDX-License-Identifier: BSD-3-Clause
5
6"""
7This script demonstrates how to generate log outputs while the simulation plays.
8It accompanies the tutorial on docker usage.
9
10.. code-block:: bash
11
12 # Usage
13 ./isaaclab.sh -p source/standalone/tutorials/00_sim/log_time.py
14
15"""
16
17"""Launch Isaac Sim Simulator first."""
18
19
20import argparse
21import os
22
23from omni.isaac.lab.app import AppLauncher
24
25# create argparser
26parser = argparse.ArgumentParser(description="Tutorial on creating logs from within the docker container.")
27# append AppLauncher cli args
28AppLauncher.add_app_launcher_args(parser)
29# parse the arguments
30args_cli = parser.parse_args()
31# launch omniverse app
32app_launcher = AppLauncher(args_cli)
33simulation_app = app_launcher.app
34
35"""Rest everything follows."""
36
37from omni.isaac.lab.sim import SimulationCfg, SimulationContext
38
39
40def main():
41 """Main function."""
42 # Specify that the logs must be in logs/docker_tutorial
43 log_dir_path = os.path.join("logs")
44 if not os.path.isdir(log_dir_path):
45 os.mkdir(log_dir_path)
46 # In the container, the absolute path will be
47 # /workspace/isaaclab/logs/docker_tutorial, because
48 # all python execution is done through /workspace/isaaclab/isaaclab.sh
49 # and the calling process' path will be /workspace/isaaclab
50 log_dir_path = os.path.abspath(os.path.join(log_dir_path, "docker_tutorial"))
51 if not os.path.isdir(log_dir_path):
52 os.mkdir(log_dir_path)
53 print(f"[INFO] Logging experiment to directory: {log_dir_path}")
54
55 # Initialize the simulation context
56 sim_cfg = SimulationCfg(dt=0.01)
57 sim = SimulationContext(sim_cfg)
58 # Set main camera
59 sim.set_camera_view([2.5, 2.5, 2.5], [0.0, 0.0, 0.0])
60
61 # Play the simulator
62 sim.reset()
63 # Now we are ready!
64 print("[INFO]: Setup complete...")
65
66 # Prepare to count sim_time
67 sim_dt = sim.get_physics_dt()
68 sim_time = 0.0
69
70 # Open logging file
71 with open(os.path.join(log_dir_path, "log.txt"), "w") as log_file:
72 # Simulate physics
73 while simulation_app.is_running():
74 log_file.write(f"{sim_time}" + "\n")
75 # perform step
76 sim.step()
77 sim_time += sim_dt
78
79
80if __name__ == "__main__":
81 # run the main function
82 main()
83 # close sim app
84 simulation_app.close()
The Code Explained#
The Isaac Lab Docker container has several volumes to facilitate persistent storage between the host computer and the
container. One such volume is the /workspace/isaaclab/logs
directory.
The log_time.py
script designates this directory as the location to which a log.txt
should be written:
# Specify that the logs must be in logs/docker_tutorial
log_dir_path = os.path.join("logs")
if not os.path.isdir(log_dir_path):
os.mkdir(log_dir_path)
# In the container, the absolute path will be
# /workspace/isaaclab/logs/docker_tutorial, because
# all python execution is done through /workspace/isaaclab/isaaclab.sh
# and the calling process' path will be /workspace/isaaclab
log_dir_path = os.path.abspath(os.path.join(log_dir_path, "docker_tutorial"))
if not os.path.isdir(log_dir_path):
os.mkdir(log_dir_path)
print(f"[INFO] Logging experiment to directory: {log_dir_path}")
As the comments note, os.path.abspath()
will prepend /workspace/isaaclab
because in
the Docker container all python execution is done through /workspace/isaaclab/isaaclab.sh
.
The output will be a file, log.txt
, with the sim_time
written on a newline at every simulation step:
# Prepare to count sim_time
sim_dt = sim.get_physics_dt()
sim_time = 0.0
# Open logging file
with open(os.path.join(log_dir_path, "log.txt"), "w") as log_file:
# Simulate physics
while simulation_app.is_running():
log_file.write(f"{sim_time}" + "\n")
# perform step
sim.step()
sim_time += sim_dt
Executing the Script#
We will execute the script to produce a log, adding a --headless
flag to our execution to prevent a GUI:
isaaclab -p source/standalone/tutorials/00_sim/log_time.py --headless
Now log.txt
will have been produced at /workspace/isaaclab/logs/docker_tutorial
. If we exit the container
by typing exit
, we will return to IsaacLab/docker
in our host terminal environment. We can then enter
the following command to retrieve our logs from the Docker container and put them on our host machine:
./container.py copy
We will see a terminal readout reporting the artifacts we have retrieved from the container. If we navigate to
/isaaclab/docker/artifacts/logs/docker_tutorial
, we will see a copy of the log.txt
file which was produced
by the script above.
Each of the directories under artifacts
corresponds to Docker volumes mapped to directories
within the container and the container.py copy
command copies them from those volumes to these directories.
We could return to the Isaac Lab Docker terminal environment by running container.py enter
again,
but we have retrieved our logs and wish to go inspect them. We can stop the Isaac Lab Docker container with the following command:
./container.py stop
This will bring down the Docker Isaac Lab container. The image will persist and remain available for further use, as will
the contents of any volumes. If we wish to free up the disk space taken by the image, (~20.1GB), and do not mind repeating
the build process when we next run ./container.py start
, we may enter the following command to delete the isaac-lab-base image:
docker image rm isaac-lab-base
A subsequent run of docker image ls
will show that the image tagged isaac-lab-base is now gone. We can repeat the process for the
underlying NVIDIA container if we wish to free up more space. If a more powerful method of freeing resources from Docker is desired,
please consult the documentation for the docker prune commands.