Skip to content

Modifies ROOT user related setup to Dockerfile.curobo#5376

Open
njawale42 wants to merge 5 commits intoisaac-sim:developfrom
njawale42:neel/dockerfile-curobo-remove-root-user
Open

Modifies ROOT user related setup to Dockerfile.curobo#5376
njawale42 wants to merge 5 commits intoisaac-sim:developfrom
njawale42:neel/dockerfile-curobo-remove-root-user

Conversation

@njawale42
Copy link
Copy Markdown
Contributor

@njawale42 njawale42 commented Apr 23, 2026

Description

Refactors docker/Dockerfile.curobo so the editable Isaac Lab installs and the final container runtime drop privileges to the non-root isaac-sim user (uid 1234) provided by the base image (nvcr.io/nvidian/isaac-sim:latest-develop, see upstream Isaac Sim Dockerfile). The CI image (build-curobotest-curobo / test-skillgen) currently runs as root the whole way, even though the base image already moved to a non-root default.

What changed

  1. Explicit USER root for the system-level setup block. apt, cuda-keyring repo, install_deps.py apt, ${DOCKER_USER_HOME} cache dirs, /bin/nvidia-* placeholders, the pre-bundled torch removal, and the get-pip.py bootstrap all require root and stay as root.
  2. chown + USER isaac-sim before the pip installs. Only the paths we still need to write to are chowned (${ISAACLAB_PATH}, ${ISAACSIM_ROOT_PATH}/kit/python/.../site-packages, ${DOCKER_USER_HOME}) — /isaac-sim is already isaac-sim-owned by the base image, so re-chowning it would needlessly bloat the layer.
  3. BuildKit cache mount pinned to uid=1234,gid=1234 for ${DOCKER_USER_HOME}/.cache/pip, otherwise the default root-owned cache mount would be unwritable from isaac-sim.
  4. ${HOME}/.bashrc used consistently in the alias RUN block. Two lines hardcoded /root/.bashrc while the surrounding 8 lines used ${HOME}/.bashrc; after the user switch this inconsistency would silently land the trailing config in the wrong file.
  5. Final COPY annotated with --chown=isaac-sim:isaac-sim for ownership consistency.

CI build args (DOCKER_USER_HOME_ARG=/root in .github/actions/ecr-build-push-pull/action.yml, .github/actions/docker-build/action.yml, and .github/workflows/postmerge-ci.yml) are unchanged — /root is chowned to isaac-sim inside the image, so they continue to work.

Scope

docker/Dockerfile.base and docker/Dockerfile.ros2 follow the same legacy root-everywhere pattern but are also consumed by docker/docker-compose.yaml (which sets OMNI_KIT_ALLOW_ROOT=1 and binds ${DOCKER_USER_HOME} paths). Migrating those needs coordinated changes to the compose file and CI build args, so they're left for a follow-up PR.

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Checklist

  • I have read and understood the contribution guidelines
  • I have run the pre-commit checks with ./isaaclab.sh --format
  • I have made corresponding changes to the documentation
  • 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
  • I have added my name to the CONTRIBUTORS.md or my name already exists there

The NVIDIA Isaac Sim base image declares no USER directive and defaults
to root, so the explicit USER root in this Dockerfile is a no-op
declaration. Removing it aligns Dockerfile.curobo with the upstream
NVIDIA Isaac Sim Dockerfile and with the other Isaac Lab Dockerfiles
(Dockerfile.ros2, Dockerfile.installci) which omit the directive.

Build and runtime behavior are unchanged: the container still runs as
root via the base image default.
Copy link
Copy Markdown

@isaaclab-review-bot isaaclab-review-bot Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Isaac Lab Review Bot

Summary

This PR makes two minor cleanup changes to docker/Dockerfile.curobo: (1) removes a redundant USER root directive since the base image already defaults to root, and (2) changes two hardcoded /root/.bashrc references to use ${HOME}/.bashrc for consistency with the 8 preceding lines in the same RUN block. The changes are correct and improve maintainability.

Architecture Impact

Self-contained. This is a Docker build configuration change that affects only the cuRobo container image build process. No runtime code, no Isaac Lab framework code, and no other Dockerfiles are impacted. The container behavior remains identical since ${HOME} resolves to /root in the current configuration.

Implementation Verdict

Ship it

Test Coverage

No tests required. This is a Docker configuration cleanup with no behavioral change. The PR author's claim that "the container still builds and runs identically" is correct — both changes are purely cosmetic consistency improvements. Manual verification that the container builds successfully would be the appropriate validation, which is covered by standard CI Docker builds if available.

CI Status

No CI checks available yet. Once CI runs, the Docker build job (if present) would validate this change.

Findings

🔵 Improvement: docker/Dockerfile.curobo:34 — Removal of USER root is correct
The NVIDIA Isaac Sim base image does not set a non-root user, so this directive was indeed a no-op. Removing it aligns with the upstream Dockerfile style and reduces noise.

🔵 Improvement: docker/Dockerfile.curobo:170-171 — Consistent use of ${HOME} is correct
The change from /root/.bashrc to ${HOME}/.bashrc makes the entire RUN block internally consistent. While HOME=/root in the current build context, using the variable is more maintainable if the base image ever changes or if the Dockerfile is adapted for non-root users in the future.

Verification note: I confirmed that ${HOME} is the correct variable to use here by examining the full file context. The DOCKER_USER_HOME environment variable (line 33) is a different variable intended for bind-mount paths in Singularity (lines 116-123), while ${HOME} is the standard shell variable used throughout the alias block. The PR correctly uses ${HOME} to match the existing pattern.

No critical or warning-level issues identified. This is a clean, low-risk cleanup PR.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 23, 2026

Greptile Summary

This PR refactors docker/Dockerfile.curobo to drop privileges from root by creating a new isaaclab user (uid 1000) before pip installs, fixes two hardcoded /root/.bashrc lines, and adds --chown to the final COPY. There are two P1 concerns worth addressing before merge.

  • The chown -R path ${ISAACSIM_ROOT_PATH}/kit/python/lib/python3.12/site-packages hard-codes python3.12; if the base image ships a different Python minor version the build will fail with "No such file or directory."
  • useradd sets the new user's $HOME to /home/isaaclab, but all singularity cache directories (.cache/ov, .nv, .nvidia-omniverse, etc.) are still created under $DOCKER_USER_HOME (= /root). Tools that resolve caches via $HOME/XDG conventions will look in the wrong place at runtime.

Confidence Score: 3/5

Not safe to merge as-is — two P1 issues: a build-breaking hardcoded Python path and a HOME/DOCKER_USER_HOME mismatch that orphans pre-created cache directories at runtime.

Two P1 findings: the hardcoded python3.12 path in chown will break the build when the base image upgrades Python, and the divergence between $HOME=/home/isaaclab and $DOCKER_USER_HOME=/root means Omniverse/pip cache dirs won't be found by tools using standard home-directory conventions.

docker/Dockerfile.curobo — both P1 issues are in the new user-setup block (lines 157-165)

Important Files Changed

Filename Overview
docker/Dockerfile.curobo Adds USER root guard, creates isaaclab user (uid 1000), chowns key paths, and drops to non-root for pip installs; has two P1 issues: hardcoded python3.12 path in chown and $HOME vs $DOCKER_USER_HOME directory mismatch.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[FROM base image\ninitial user: isaac-sim uid=1234] --> B[USER root]
    B --> C[apt installs / CUDA keyring\ncuda-toolkit-12-8 etc.]
    C --> D[COPY source files\nno chown - root-owned]
    D --> E[pip install toml / apt deps\ncreate singularity dirs under DOCKER_USER_HOME=/root\nnvidia placeholders / reinstall pip]
    E --> F[useradd isaaclab uid=1000\nhome=/home/isaaclab]
    F --> G[chown -R isaaclab:isaaclab\n ISAACLAB_PATH\n kit/python/lib/python3.12/site-packages ⚠️\n DOCKER_USER_HOME=/root\n /home/isaaclab]
    G --> H[USER isaaclab]
    H --> I[pip cache mount uid=1000\nisaaclab.sh --install\npip installs cuRobo / teleop]
    I --> J[bashrc aliases\nHOME=/home/isaaclab ⚠️ vs DOCKER_USER_HOME=/root]
    J --> K[COPY --chown=isaaclab:isaaclab\nall remaining files]
    K --> L[WORKDIR ISAACLAB_PATH\nruntime as isaaclab uid=1000]
Loading

Reviews (3): Last reviewed commit: "Runs Dockerfile.curobo as new isaaclab u..." | Re-trigger Greptile

…ile.curobo

The base image (nvcr.io/nvidian/isaac-sim:latest-develop) ends with
USER isaac-sim (uid 1234). Previously the Dockerfile switched back to
root for the entire build and left runtime as root via
OMNI_KIT_ALLOW_ROOT. Removing the initial USER root broke CI because
apt needs root; simply restoring it keeps us as root the whole way
which is what we want to avoid.

Correct pattern applied here:

  * Explicit USER root for the system-level setup block (apt, cuda
    repo, /bin/nvidia-* placeholders, /root cache dirs, get-pip
    bootstrap, COPYed source files).
  * After the last root-required step, chown only the paths we are
    about to write to from the non-root user
    (${ISAACLAB_PATH}, site-packages, ${DOCKER_USER_HOME}) to
    isaac-sim:isaac-sim. /isaac-sim itself is already isaac-sim-owned
    from the base image, so re-chowning it would needlessly bloat
    the layer.
  * USER isaac-sim before the editable pip installs
    (isaaclab.sh --install, cuRobo, isaaclab_teleop) and the bashrc
    writes, so those paths end up owned by the runtime user.
  * BuildKit cache mount at ${DOCKER_USER_HOME}/.cache/pip pinned to
    uid=1234,gid=1234, otherwise it would default to root-owned and
    isaac-sim could not write into it.
  * Final COPY annotated with --chown=isaac-sim:isaac-sim for
    consistency.

This keeps CI build args (DOCKER_USER_HOME_ARG=/root) and
docker-compose paths unchanged, so docker-compose usage continues to
work with OMNI_KIT_ALLOW_ROOT. Dockerfile.base and Dockerfile.ros2
follow the same legacy pattern and are out of scope for this PR.
@njawale42
Copy link
Copy Markdown
Contributor Author

@greptileai

@njawale42 njawale42 changed the title Removes redundant USER root and inconsistent /root/.bashrc from Dockerfile.curobo ROOT user related modifications to Dockerfile.curobo Apr 23, 2026
… compat

The previous attempt switched to the base image's isaac-sim user (uid 1234),
which broke the test step in CI: the test runner bind-mounts the host
workspace (/opt/github-runner/_work/.../IsaacLab, owned by uid 1000) over
/workspace/isaaclab, overlaying our build-time chown. As uid 1234, the
container could not write to the bind mount and `mkdir tests` failed before
pytest even started.

Fix: create a fresh isaaclab user with uid 1000 to match the runner host
user, instead of remapping isaac-sim. Creating a new user (rather than
remapping isaac-sim's UID) avoids triggering an OverlayFS copy-up of the
multi-GB Isaac Sim install in /isaac-sim, which would otherwise become
orphan-owned. /isaac-sim stays mode 755 and isaac-sim-owned, so isaaclab
can still read and execute everything there. Only the paths the new user
needs to write to (${ISAACLAB_PATH}, kit site-packages, ${DOCKER_USER_HOME},
/home/isaaclab) are chowned.

Also bumps the BuildKit pip cache mount uid/gid from 1234 to 1000 (numeric
form is required because BuildKit does not consult /etc/passwd at mount
time) and switches the final COPY --chown to isaaclab.

Caveat: hardcodes uid 1000, matching the typical EC2 self-hosted runner
user. If a runner is reconfigured to a different uid this will break the
same way; in that case the right next step is to parameterize via build
arg, but until then 1000 is the simplest correct value.
Comment thread docker/Dockerfile.curobo

RUN chown -R isaaclab:isaaclab \
${ISAACLAB_PATH} \
${ISAACSIM_ROOT_PATH}/kit/python/lib/python3.12/site-packages \
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Hardcoded Python version will break on base-image upgrade

python3.12 is hard-coded in the chown path. If the upstream Isaac Sim base image ships Python 3.13 (or any other version), this path won't exist and the RUN chown -R layer will fail at build time with "No such file or directory," breaking the entire image build.

Use a glob or a shell expansion to resolve the versioned directory dynamically:

Suggested change
${ISAACSIM_ROOT_PATH}/kit/python/lib/python3.12/site-packages \
$(ls -d ${ISAACSIM_ROOT_PATH}/kit/python/lib/python3.*/site-packages 2>/dev/null | head -1) \

Comment thread docker/Dockerfile.curobo
Comment on lines +157 to +165
RUN useradd -ms /bin/bash -l --uid 1000 isaaclab -d /home/isaaclab

RUN chown -R isaaclab:isaaclab \
${ISAACLAB_PATH} \
${ISAACSIM_ROOT_PATH}/kit/python/lib/python3.12/site-packages \
${DOCKER_USER_HOME} \
/home/isaaclab

USER isaaclab
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 $HOME and $DOCKER_USER_HOME point to different directories

useradd -d /home/isaaclab sets the isaaclab user's $HOME to /home/isaaclab. However, DOCKER_USER_HOME (passed in as /root from CI build args) is what drives the singularity cache-directory setup: mkdir -p ${DOCKER_USER_HOME}/.cache/ov, ${DOCKER_USER_HOME}/.nv, ${DOCKER_USER_HOME}/.nvidia-omniverse, etc., all land under /root/.

At runtime any tool that resolves its cache via $HOME (standard XDG behaviour, ~) will look in /home/isaaclab/ — where those dirs don't exist — rather than in /root/. The pre-created directories under $DOCKER_USER_HOME=/root will be orphaned for those tools.

Consider one of:

  • Setting DOCKER_USER_HOME_ARG=/home/isaaclab in CI so the singularity dirs are created under the user's real home, or
  • Keeping DOCKER_USER_HOME=/root but additionally creating the same set of subdirectories (or symlinks) under /home/isaaclab/ so both $HOME-based and $DOCKER_USER_HOME-based lookups succeed.

@kellyguo11 kellyguo11 changed the title ROOT user related modifications to Dockerfile.curobo Modifies ROOT user related setup to Dockerfile.curobo Apr 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants