Fix/rheo dockerfile - #231
Conversation
Greptile SummaryThis PR overhauls the Rheo Docker build pipeline for RTX 50-series (Blackwell) GPU stability and fixes several runtime issues: it replaces the monolithic
Confidence Score: 3/5The builtins.open monkey-patch in register_and_patch.py will crash with TypeError for any open(bytes_path) call after it is installed — a global side-effect that could surface in any third-party library used at runtime. The _patch_lightwheel_cache_writes function replaces builtins.open process-wide but does not handle bytes file arguments: os.fspath(b'/path') returns bytes, and the subsequent str_marker in bytes_path raises TypeError. This breaks all code that legitimately passes a bytes path to open() after the patch is active, including any C-extension or third-party package that does so. workflows/rheo/scripts/simulation/register_and_patch.py (bytes-path branch of the builtins.open patch) and workflows/rheo/scripts/utils/blackwell_render.py (_merge_kit_arg_values substring conflict). Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant Host as Host (run_docker.sh)
participant Docker as Docker Container
participant Kit as Isaac Sim Kit Python
participant Reg as register_and_patch.py
participant App as SimulationApp
Host->>Host: "mkdir -p ~/.cache/lightwheel_sdk/object/*"
Host->>Host: "Blackwell: unset DISPLAY (HEADLESS=1)"
Host->>Docker: docker run (mounts host cache)
Note over Docker: ENV HEADLESS=1, PYTHONPATH includes workflows/rheo
Docker->>Reg: import register_and_patch → register_workflow_cli()
Reg->>Kit: ensure_blackwell_safe_kit_args() injects --kit_args into sys.argv
Docker->>App: SimulationAppContext(args_cli) starts Kit
App-->>Docker: Kit initialized with Blackwell flags
Docker->>Reg: register_workflow_assets()
Reg->>Reg: _skip_eager_arena_registry() patches AssetRegistry temporarily
Reg->>Reg: _patch_lightwheel_cache_writes() patches builtins.open
Reg->>Reg: import asset modules (no eager Arena registry load)
Docker->>App: "gym.make(env_name, cfg=env_cfg)"
App->>App: apply_blackwell_safe_render_cfg(sim.render)
Note over App: performance mode, translucency off, shadows off
Docker->>App: env.step() loop + optional video recording
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant Host as Host (run_docker.sh)
participant Docker as Docker Container
participant Kit as Isaac Sim Kit Python
participant Reg as register_and_patch.py
participant App as SimulationApp
Host->>Host: "mkdir -p ~/.cache/lightwheel_sdk/object/*"
Host->>Host: "Blackwell: unset DISPLAY (HEADLESS=1)"
Host->>Docker: docker run (mounts host cache)
Note over Docker: ENV HEADLESS=1, PYTHONPATH includes workflows/rheo
Docker->>Reg: import register_and_patch → register_workflow_cli()
Reg->>Kit: ensure_blackwell_safe_kit_args() injects --kit_args into sys.argv
Docker->>App: SimulationAppContext(args_cli) starts Kit
App-->>Docker: Kit initialized with Blackwell flags
Docker->>Reg: register_workflow_assets()
Reg->>Reg: _skip_eager_arena_registry() patches AssetRegistry temporarily
Reg->>Reg: _patch_lightwheel_cache_writes() patches builtins.open
Reg->>Reg: import asset modules (no eager Arena registry load)
Docker->>App: "gym.make(env_name, cfg=env_cfg)"
App->>App: apply_blackwell_safe_render_cfg(sim.render)
Note over App: performance mode, translucency off, shadows off
Docker->>App: env.step() loop + optional video recording
Reviews (4): Last reviewed commit: "Dockerfile" | Re-trigger Greptile |
| hidapi==0.14.0.post2 \ | ||
| starlette==0.49.1 \ | ||
| "pyglet<2" | ||
| RUN ${ISAACLAB_PATH}/isaaclab.sh -p -m pip install --no-build-isolation --prefer-binary "onnx>=1.18.0" |
There was a problem hiding this comment.
onnx version overwritten by GR00T block
This PR newly installs onnx>=1.18.0 here, but when INSTALL_GROOT=true the GR00T block later runs pip install ... onnx==1.17.0 (line 219), which downgrades it. Any code that depends on onnx 1.18+ APIs (or the onnxruntime install assuming onnx 1.18+) would fail at runtime with that build configuration.
| RUN ${ISAACLAB_PATH}/isaaclab.sh -p -m pip install --no-build-isolation --prefer-binary \ | ||
| prettytable==3.3.0 \ | ||
| gymnasium==1.2.1 \ | ||
| pillow==11.3.0 \ | ||
| hidapi==0.14.0.post2 \ | ||
| starlette==0.49.1 \ | ||
| "pyglet<2" |
There was a problem hiding this comment.
gymnasium pinned to 1.2.1 here, overwritten to 1.0.0 by GR00T block
This PR explicitly pins gymnasium==1.2.1, but when INSTALL_GROOT=true the GR00T stage installs gymnasium==1.0.0 (line 208), which pip will downgrade to. Gymnasium 1.0.0 has API differences from 1.2.x; if any IsaacLab extension depends on 1.2-era APIs, it would fail silently with a wrong-version import at runtime. matplotlib is similarly pinned to 3.10.3 here and then overwritten to 3.10.0 in the GR00T block.
| starlette==0.49.1 \ | ||
| "pyglet<2" | ||
| RUN ${ISAACLAB_PATH}/isaaclab.sh -p -m pip install --no-build-isolation --prefer-binary "onnx>=1.18.0" | ||
| RUN ${ISAACLAB_PATH}/isaaclab.sh -p -m pip install --no-build-isolation --prefer-binary warp-lang |
There was a problem hiding this comment.
Every other package in the surrounding block is version-pinned, but warp-lang floats. A breaking release from NVIDIA (Warp has had API changes across minor versions) would silently produce a different image with no indication in the Dockerfile. Consider pinning to the specific version you validated against.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| "protobuf>=4.25.8,!=5.26.0" \ | ||
| "packaging<24" |
There was a problem hiding this comment.
protobuf base requirement overwritten by GR00T block
This PR newly adds "protobuf>=4.25.8,!=5.26.0" to the base section (protobuf 4.x is required by isaaclab/tensorboard). When INSTALL_GROOT=true, the GR00T block later runs pip install ... protobuf==3.20.3 (line 229), which downgrades to a 3.x release that does not satisfy >=4.25.8. Any isaaclab component that relies on protobuf 4.x binary APIs will fail at runtime in GR00T builds. This follows the same pattern as the onnx/gymnasium version conflicts noted in previous review threads.
Mitigate RTX 50-series crashes via Kit args, conservative render presets, and headless DISPLAY handling; add --save_video to observe/policy runners.
| def _open_with_lightwheel_cache_dirs(file, *args, **kwargs): | ||
| if isinstance(file, (str, bytes, os.PathLike)): | ||
| path = os.fspath(file) | ||
| marker = f"{os.sep}.cache{os.sep}lightwheel_sdk{os.sep}object{os.sep}" | ||
| if marker in path: |
There was a problem hiding this comment.
open(bytes_path) raises TypeError after this patch is applied
os.fspath(file) returns bytes when file is a bytes object, but marker is always a str. The expression marker in path raises TypeError: a bytes-like object is required, not 'str' in Python 3 when path is bytes. Because this replaces builtins.open globally, any third-party library that legitimately calls open(b"/some/path") after this patch is installed will crash with an unhandled TypeError instead of opening the file.
| def _open_with_lightwheel_cache_dirs(file, *args, **kwargs): | |
| if isinstance(file, (str, bytes, os.PathLike)): | |
| path = os.fspath(file) | |
| marker = f"{os.sep}.cache{os.sep}lightwheel_sdk{os.sep}object{os.sep}" | |
| if marker in path: | |
| def _open_with_lightwheel_cache_dirs(file, *args, **kwargs): | |
| if isinstance(file, (str, bytes, os.PathLike)): | |
| path = os.fspath(file) | |
| marker_str = f"{os.sep}.cache{os.sep}lightwheel_sdk{os.sep}object{os.sep}" | |
| marker = marker_str.encode() if isinstance(path, bytes) else marker_str | |
| if marker in path: |
Fixes #ISSUE_NUMBER
Description