Skip to content

perf: reduce sandbox image build time and size during onboarding - #855

Merged
ericksoa merged 4 commits into
mainfrom
fix/optimize-sandbox-image-builds
Apr 6, 2026
Merged

ericksoa merged 4 commits into
mainfrom
fix/optimize-sandbox-image-builds

Conversation

@kjw3

@kjw3 kjw3 commented Mar 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Reduce NemoClaw sandbox image build cost during onboarding without changing functionality or weakening the current security model.

This PR keeps the existing monolithic image approach, but trims unnecessary build/runtime overhead and adds a repeatable benchmark for comparing image build performance against origin/main.

What Changed

  • stage a minimal sandbox build context instead of copying whole source trees
  • exclude nemoclaw-blueprint/.venv from the staged context
  • stage only the blueprint files the Docker build actually consumes
  • switch plugin installs from npm install to lockfile-backed npm ci
  • remove unused runtime packages from the sandbox image:
    • python3-pip
    • python3-venv
    • iproute2
    • build-time PyYAML
  • prune clearly non-runtime OpenClaw package content after install:
    • docs
    • READMEs
    • changelogs
    • source maps
  • add benchmark tooling for origin/main vs current branch sandbox image builds

Security / Behavior

This PR is intentionally scoped to image build optimization and does not change the core security model.

Preserved:

  • immutable openclaw.json / config-hash protection
  • gateway vs sandbox user separation
  • no credential values in CLI argv
  • no sandbox secret env injection during sandbox create
  • Dockerfile arg-to-env injection guard for the Python config generation step

Security validation still passes, including the gateway isolation end-to-end test.

Validation

Repo checks:

  • npx vitest run test/sandbox-build-context.test.js test/onboard.test.js test/security-c2-dockerfile-injection.test.js test/credential-exposure.test.js test/runner.test.js
  • git diff --check
  • bash -n test/e2e-test.sh test/e2e-gateway-isolation.sh

Container/security checks:

  • bash test/e2e-gateway-isolation.sh
  • result: 10 passed, 0 failed

Benchmark:

  • node scripts/benchmark-sandbox-image-build.js

Latest result:

  • main (93a475a): 74.2s, 1493.0 MiB
  • candidate: 40.8s, 1165.7 MiB

Delta:

  • build time: 33.4s faster
  • image size: 327.3 MiB smaller

Follow-up

The next larger step is tracked separately in #854:

  • reusable nemoclaw-base image
  • thin per-onboard top image
  • optional uninstall purge for cached/base images
  • possible GHCR publishing flow

Summary by CodeRabbit

  • New Features

    • Added build performance benchmarking capability to compare sandbox image build strategies.
  • Refactor

    • Optimized Docker build process with deterministic dependency installation and reduced build context size for faster, more efficient builds.
  • Tests

    • Added test coverage for build-context staging and validation.

@coderabbitai

coderabbitai Bot commented Mar 25, 2026 •

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b407fde8-c971-4114-ae7e-9fd68801c8d4

📥 Commits

Reviewing files that changed from the base of the PR and between 2f45a12 and 5c376e1.

📒 Files selected for processing (5)
  • Dockerfile
  • bin/lib/onboard.js
  • bin/lib/sandbox-build-context.js
  • test/onboard.test.js
  • test/sandbox-build-context.test.js
✅ Files skipped from review due to trivial changes (3)
  • test/sandbox-build-context.test.js
  • test/onboard.test.js
  • bin/lib/sandbox-build-context.js
🚧 Files skipped from review as they are similar to previous changes (2)
  • Dockerfile
  • bin/lib/onboard.js

📝 Walkthrough

Walkthrough

This PR refactors Docker sandbox build-context staging by extracting inline logic into a dedicated module supporting both legacy and optimized strategies. The optimized approach reduces build-context size by selectively copying essential files (package metadata, source code, minimal scripts) instead of entire directories. Integration into the primary onboarding workflow is simplified, and new benchmarking and test utilities validate performance improvements and prevent regressions.

Changes

Cohort / File(s) Summary
Docker Configuration
Dockerfile
Added npm configuration (npm ci over npm install), enabled lockfile-based deterministic installs with package-lock.json in build context, and expanded npm cleanup in runtime stage to remove cached artifacts from /root/.npm and /sandbox/.npm.
Build Context Staging
bin/lib/sandbox-build-context.js
New module exporting staging utilities: stageLegacySandboxBuildContext copies full directories (nemoclaw, nemoclaw-blueprint, scripts) with node_modules deletion; stageOptimizedSandboxBuildContext creates minimal contexts by copying only selected metadata/source files and essential scripts; both strategies return build-context path and staged Dockerfile path. Includes collectBuildContextStats to measure file counts and byte sizes.
Core Integration
bin/lib/onboard.js
Replaced inline build-context staging logic (temp directory creation, selective copying) with single call to stageOptimizedSandboxBuildContext, streamlining sandbox creation workflow.
Benchmarking & Validation
scripts/benchmark-sandbox-image-build.js
New CLI script benchmarking Docker image builds across legacy and optimized staging strategies. Creates temporary git worktrees, performs timed builds with both strategies, collects context statistics and image sizes, reports build-time and size deltas, with comprehensive error handling and cleanup.
Testing
test/onboard.test.js, test/sandbox-build-context.test.js
Added test cases verifying optimized staging includes required artifacts (package metadata, src, minimal scripts, Dockerfile) and excludes unneeded files (node_modules, .venv, non-essential scripts); validates optimized contexts contain fewer files and lower byte totals than legacy counterparts.
E2E Blueprint Validation
test/e2e-test.sh
Replaced Python YAML validation with Node.js ES-module approach using yaml package for blueprint parsing and profile verification.

Sequence Diagram

sequenceDiagram
    actor User
    participant CLI as benchmark-sandbox-image-build.js
    participant Git as Git
    participant Staging as Staging Logic
    participant Docker as Docker
    participant FS as File System

    User->>CLI: Run benchmark script
    activate CLI
    
    CLI->>Git: Create detached worktree at main-ref
    Git-->>CLI: Worktree ready
    
    rect rgba(255, 200, 100, 0.5)
        Note over CLI,Docker: Legacy Build Cycle
        CLI->>Staging: stageLegacySandboxBuildContext()
        Staging->>FS: Copy nemoclaw, nemoclaw-blueprint, scripts
        Staging->>FS: Remove node_modules
        Staging-->>CLI: buildCtx path, stats
        CLI->>Docker: docker build (legacy)
        Docker-->>CLI: Build time, image size
    end
    
    rect rgba(100, 200, 255, 0.5)
        Note over CLI,Docker: Optimized Build Cycle
        CLI->>Staging: stageOptimizedSandboxBuildContext()
        Staging->>FS: Copy selective files (metadata, src, nemoclaw-start.sh)
        Staging-->>CLI: buildCtx path, stats
        CLI->>Docker: docker build (optimized)
        Docker-->>CLI: Build time, image size
    end
    
    CLI->>CLI: Calculate deltas
    CLI->>User: Print summary & comparison
    
    CLI->>FS: Clean up temporary directories
    CLI->>Docker: Remove temporary image tags
    CLI->>Git: Remove temporary worktree
    
    deactivate CLI
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Hop, hop! Smaller contexts we stage with care,
Optimized builds now fill the Docker air,
Legacy strategies kept—a safety net,
Benchmarked, tested, no regrets we bet!
From nested loops to measured performance cheer,
The sandbox builds are speedy this season, my dear! 🐇

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the primary change: optimizing sandbox image builds during onboarding by reducing both build time and final image size.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/optimize-sandbox-image-builds

Comment @coderabbitai help to get the list of available commands and usage tips.

@wscurran

Copy link
Copy Markdown
Contributor

✨ Thanks for submitting this PR with a detailed summary, it proposes a fix to improve the performance of NemoClaw.

Merge main into fix/optimize-sandbox-image-builds, resolving four
conflicts:
- Dockerfile: take main's base-image approach (monolithic layers now
  in Dockerfile.base), keep PR's builder improvements (npm ci, ENV)
- bin/lib/onboard.js: combine main's pRetry/envInt/redact with PR's
  stageOptimizedSandboxBuildContext
- test/onboard.test.js: keep both main's new helper tests and PR's
  build context test
- scripts/setup.sh: accept main's deletion (superseded by nemoclaw
  onboard)

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>

@ericksoa ericksoa left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Merge conflicts resolved, all 1012 unit tests pass, pre-commit hooks clean, nightly e2e validated.

@ericksoa
ericksoa merged commit 8465218 into main Apr 6, 2026
15 of 17 checks passed
@ericksoa
ericksoa deleted the fix/optimize-sandbox-image-builds branch April 6, 2026 01:45
tranzmatt pushed a commit to tranzmatt/NemoClaw that referenced this pull request Apr 6, 2026
…DIA#855)

## Summary

Reduce NemoClaw sandbox image build cost during onboarding without
changing functionality or weakening the current security model.

This PR keeps the existing monolithic image approach, but trims
unnecessary build/runtime overhead and adds a repeatable benchmark for
comparing image build performance against `origin/main`.

## What Changed

- stage a minimal sandbox build context instead of copying whole source
trees
- exclude `nemoclaw-blueprint/.venv` from the staged context
- stage only the blueprint files the Docker build actually consumes
- switch plugin installs from `npm install` to lockfile-backed `npm ci`
- remove unused runtime packages from the sandbox image:
  - `python3-pip`
  - `python3-venv`
  - `iproute2`
  - build-time `PyYAML`
- prune clearly non-runtime OpenClaw package content after install:
  - docs
  - READMEs
  - changelogs
  - source maps
- add benchmark tooling for `origin/main` vs current branch sandbox
image builds

## Security / Behavior

This PR is intentionally scoped to image build optimization and does not
change the core security model.

Preserved:
- immutable `openclaw.json` / config-hash protection
- gateway vs sandbox user separation
- no credential values in CLI argv
- no sandbox secret env injection during sandbox create
- Dockerfile arg-to-env injection guard for the Python config generation
step

Security validation still passes, including the gateway isolation
end-to-end test.

## Validation

Repo checks:
- `npx vitest run test/sandbox-build-context.test.js
test/onboard.test.js test/security-c2-dockerfile-injection.test.js
test/credential-exposure.test.js test/runner.test.js`
- `git diff --check`
- `bash -n test/e2e-test.sh test/e2e-gateway-isolation.sh`

Container/security checks:
- `bash test/e2e-gateway-isolation.sh`
- result: `10 passed`, `0 failed`

Benchmark:
- `node scripts/benchmark-sandbox-image-build.js`

Latest result:
- `main (93a475a)`: `74.2s`, `1493.0 MiB`
- `candidate`: `40.8s`, `1165.7 MiB`

Delta:
- build time: `33.4s` faster
- image size: `327.3 MiB` smaller

## Follow-up

The next larger step is tracked separately in NVIDIA#854:
- reusable `nemoclaw-base` image
- thin per-onboard top image
- optional uninstall purge for cached/base images
- possible GHCR publishing flow


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added build performance benchmarking capability to compare sandbox
image build strategies.

* **Refactor**
* Optimized Docker build process with deterministic dependency
installation and reduced build context size for faster, more efficient
builds.

* **Tests**
  * Added test coverage for build-context staging and validation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Co-authored-by: Aaron Erickson <aerickson@nvidia.com>
gemini2026 pushed a commit to gemini2026/NemoClaw that referenced this pull request Apr 14, 2026
…DIA#855)

## Summary

Reduce NemoClaw sandbox image build cost during onboarding without
changing functionality or weakening the current security model.

This PR keeps the existing monolithic image approach, but trims
unnecessary build/runtime overhead and adds a repeatable benchmark for
comparing image build performance against `origin/main`.

## What Changed

- stage a minimal sandbox build context instead of copying whole source
trees
- exclude `nemoclaw-blueprint/.venv` from the staged context
- stage only the blueprint files the Docker build actually consumes
- switch plugin installs from `npm install` to lockfile-backed `npm ci`
- remove unused runtime packages from the sandbox image:
  - `python3-pip`
  - `python3-venv`
  - `iproute2`
  - build-time `PyYAML`
- prune clearly non-runtime OpenClaw package content after install:
  - docs
  - READMEs
  - changelogs
  - source maps
- add benchmark tooling for `origin/main` vs current branch sandbox
image builds

## Security / Behavior

This PR is intentionally scoped to image build optimization and does not
change the core security model.

Preserved:
- immutable `openclaw.json` / config-hash protection
- gateway vs sandbox user separation
- no credential values in CLI argv
- no sandbox secret env injection during sandbox create
- Dockerfile arg-to-env injection guard for the Python config generation
step

Security validation still passes, including the gateway isolation
end-to-end test.

## Validation

Repo checks:
- `npx vitest run test/sandbox-build-context.test.js
test/onboard.test.js test/security-c2-dockerfile-injection.test.js
test/credential-exposure.test.js test/runner.test.js`
- `git diff --check`
- `bash -n test/e2e-test.sh test/e2e-gateway-isolation.sh`

Container/security checks:
- `bash test/e2e-gateway-isolation.sh`
- result: `10 passed`, `0 failed`

Benchmark:
- `node scripts/benchmark-sandbox-image-build.js`

Latest result:
- `main (93a475a)`: `74.2s`, `1493.0 MiB`
- `candidate`: `40.8s`, `1165.7 MiB`

Delta:
- build time: `33.4s` faster
- image size: `327.3 MiB` smaller

## Follow-up

The next larger step is tracked separately in NVIDIA#854:
- reusable `nemoclaw-base` image
- thin per-onboard top image
- optional uninstall purge for cached/base images
- possible GHCR publishing flow


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added build performance benchmarking capability to compare sandbox
image build strategies.

* **Refactor**
* Optimized Docker build process with deterministic dependency
installation and reduced build context size for faster, more efficient
builds.

* **Tests**
  * Added test coverage for build-context staging and validation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Co-authored-by: Aaron Erickson <aerickson@nvidia.com>
@wscurran wscurran added feature PR adds or expands user-visible functionality and removed enhancement New capability or improvement request labels Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature PR adds or expands user-visible functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants