Running Isaac Lab in Docker
Docker packages Isaac Lab and its dependencies into a reusable environment.
docker/container.py is the main entry point for running Isaac Lab in a container. It wraps
docker compose so that you do not have to remember which Dockerfile, environment files, and
volume mounts belong together — you name a profile, and the script assembles the rest.
The image it builds is also the basis for the other workflows: Running on HPC clusters converts it to an Apptainer image, and Cloud Deployment provisions a machine that runs it.
The standard Isaac Lab container depends on the Isaac Sim Docker image. By running that container, you are
implicitly agreeing to the NVIDIA Software License Agreement. If you do not agree to the EULA, do not run
that container. The kitless image contains neither Isaac Sim nor Kit.
Prerequisites
Install Docker Engine, Docker Compose, and the NVIDIA Container Toolkit.
The container is tested with Docker Engine 26.0.0 and Docker Compose 2.25.0; use these versions or
newer. Follow the post-installation steps so that Docker runs without sudo.
The Isaac Sim documentation on container installation covers the same prerequisites in more detail, including how to obtain access to the Isaac Sim image.
Due to limitations with snap, please make sure
the Isaac Lab directory is placed under the /home directory tree when using docker.
Container profiles
A profile is a Docker Compose profile:
docker-compose.yaml tags each service with one, and Compose starts only the services whose
profile is active. Naming a profile therefore selects a matched set — one service, one Dockerfile,
one set of environment files, and one image name:
Every command below takes the profile as its first positional argument and defaults to base.
Only one profile applies at a time, and the resulting image and container are both named
isaac-lab-<profile>. Pass --suffix to append a name suffix when you want several variants of
the same profile side by side. Do not use --suffix with cluster deployments, whose export
commands expect the unsuffixed image name.
For what each image actually contains and how to choose between them, see Container images.
Start, run, and retrieve results
From the repository root on the host, build and start the default base container,
then open a shell in it. Append a profile to target a different image:
Inside the container, run the logging example without a visualizer:
The script writes simulation time at each step to
/workspace/isaaclab/logs/docker_tutorial/log.txt. Stop the script with Ctrl+C
and type exit to return to the host shell. Retrieve the results before stopping
the container:
The log is now at docker/artifacts/logs/docker_tutorial/log.txt on the host.
The stop command removes the container and its Compose-managed volumes, including logs
and caches; copy out anything you need first. The image remains. To remove it after stopping, run docker image rm isaac-lab-base; the next start rebuilds it. See
Docker pruning for other cleanup options.
The image copies the repository to /workspace/isaaclab at build time, so edits made after the
build are not picked up automatically. To keep the development loop fast, the compose file
bind-mounts source, scripts, docs, and tools from the host, so changes to those
directories appear inside the container immediately. Everything else requires a rebuild.
container.py command reference
container.py command reference
Run ./docker/container.py --help to list commands and
./docker/container.py <command> --help for that command’s arguments.
Every command accepts the following arguments:
Extending the Compose configuration
--files and --env-files merge extra Compose and environment files into the generated
configuration, which is how optional components are layered on without editing the checked-in files.
Streaming to XR devices is the worked example — it adds the CloudXR Runtime service alongside
base:
Stop it with the same arguments. The teleoperation setup, firewall rules, and client connection
steps are covered in Setting up Isaac Capture with CloudXR. Use ./docker/container.py config to print the
merged result when a combination does not behave as expected.
What persists between runs
The compose file declares named volumes for Isaac Sim caches, logs, and your own data. They
remain available while reusing a container, but container.py stop runs docker compose down --volumes` and removes them. Run `container.py copy` before `stop to preserve your results
on the host.
container.py copy extracts the three volumes you are most likely to want on the host —
logs, data_storage, and docs/_build — into docker/artifacts. For anything else, use
docker cp, for example docker cp isaac-lab-base:/workspace/isaaclab/logs ..
If you are upgrading from an Isaac Lab image that ran as root, the existing volumes still hold
root-owned files that the current uid/gid 1000 runtime user cannot write. Copy out anything worth
keeping, then recreate them from the docker directory:
Run docker volume ls on the host to find the actual names, which include the Compose project
prefix, then use docker volume inspect <volume-name>. The kitless profile
uses the uv and Warp caches and shares the documentation, logs, and data volumes with the others.
Display forwarding with X11
X11 forwarding lets GUI applications started inside the container display on the host. The first
start asks whether to enable it and records the answer in docker/.container.cfg. To change it
later, set X11_FORWARDING_ENABLED to 0 or 1 in that file and run start again — the
rebuild is what applies the change.