Skip to content

Replace legacy images with Nebari-compatible images#283

Merged
asmacdo merged 4 commits into
mainfrom
nebari-images
Feb 9, 2026
Merged

Replace legacy images with Nebari-compatible images#283
asmacdo merged 4 commits into
mainfrom
nebari-images

Conversation

@asmacdo

@asmacdo asmacdo commented Dec 17, 2025

Copy link
Copy Markdown
Member

Summary

Replaces the legacy Docker images with new Nebari-compatible images that work with DandiHub.

The old images were built from scratch and didn't integrate with Nebari's JupyterHub deployment. The new images extend upstream Nebari base images, inheriting their configuration and adding DANDI-specific tools.

These images are based on the image customizations that we originally forked from nebari https://github.com/dandi/nebari-docker-images/tree/enh/dandi

What's Changed

New Image Structure

  • images/dandi/ - Extends quay.io/nebari/nebari-jupyterlab with AWS CLI, rclone, datalad, git-annex-remote-rclone
  • images/matlab/ - MATLAB integration compatible with Nebari (see MATLAB section below)
  • Removed 7 legacy Dockerfiles that don't work with Nebari

CI/CD

  • Builds all images on PR (no push) for validation
  • Pushes to Docker Hub on merge to main
  • GitHub-hosted runners are sufficient - all images build in ~3 minutes, no self-hosted infrastructure needed

Images Produced

Tag Description
dandiarchive/dandihub:latest-nebari CPU image
dandiarchive/dandihub:latest-nebari-gpu GPU/CUDA image
dandiarchive/dandihub:latest-matlab MATLAB image

MATLAB + Nebari Integration

The MATLAB base image has an ENTRYPOINT that conflicts with how Nebari spawns JupyterHub pods. The fix:

  1. Clear ENTRYPOINT - Let Nebari control pod startup
  2. Install libnss-wrapper - Required for Nebari's user identity handling
  3. Set MW_CONTEXT_TAGS - Environment variable for MATLAB licensing

Tested on staging:

  • DONE: Pod starts
  • DONE: JupyterLab loads
  • DONE: License manager appears
  • TODO: Licensing flow needs testing with actual MATLAB credentials

@aranega - This should resolve the ENTRYPOINT/licensing issues you were debugging. The key insight was that Nebari uses libnss_wrapper to handle user identity, and the MATLAB base image's start.sh was conflicting with that. By clearing the ENTRYPOINT and installing libnss-wrapper, both systems can coexist.

TODOs (prior to merge)

  • bump nebari base image tags
  • update deployment repo README, stop mentioning nebari-docker-images fork, point here.

TODOs (future PRs)

This PR focuses on Nebari compatibility (the foundation). Vincent's scientific tooling from PR #282 (toolboxes, Python packages, add-ons) should be layered on top once this is merged. These will be checked after followup issues are created.

  • Layer Vincent's tooling - Add MATLAB toolboxes, Python packages (datalad, dandi, pynwb, etc.), and add-ons from Migrate MATLAB Docker image to MATLAB 2025b #282
  • MATLAB + GPU variant - Combine MATLAB with GPU support for compute-intensive workflows
  • DANDI tools in MATLAB image - Add datalad, rclone, AWS CLI to MATLAB image for data access parity
  • Pin git-annex-remote-rclone - Currently pulls from master, should pin to a release tag
  • update tags to match deployment (or update deployment to these tags)

Fixes

Related

Test Plan

  • CI builds pass for all three images (dandi, dandi-gpu, matlab)
  • Verified images work on Nebari staging (worked at push shouldre-test after changes)
  • Vincent to test MATLAB licensing flow

- Remove old Dockerfiles that don't work with Nebari/DandiHub
- Add dandi/ with Nebari jupyterlab base + DANDI tools
- Add matlab/ with Nebari-compatible MATLAB integration
- Update workflow for new structure

The new images extend upstream Nebari images instead of
rebuilding from scratch. MATLAB fix: clear ENTRYPOINT,
add libnss-wrapper for Nebari user identity handling.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR replaces legacy Docker images with new Nebari-compatible images for DandiHub's JupyterHub deployment. The old images were built from scratch and didn't integrate with Nebari; the new images extend upstream Nebari base images and add DANDI-specific tooling.

Key changes:

  • New modular image structure with separate dandi/ and matlab/ directories extending Nebari base images
  • MATLAB image now clears ENTRYPOINT and installs libnss-wrapper for Nebari compatibility
  • Simplified CI/CD workflow using GitHub-hosted runners with separate jobs for dandi and matlab builds

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
images/dandi/Dockerfile New CPU/GPU image extending nebari-jupyterlab with AWS CLI, rclone, datalad, and git-annex-remote-rclone
images/dandi/environment.yaml Conda environment defining rclone and datalad dependencies
images/dandi/postBuild Permission fix script for multi-user conda environment
images/matlab/Dockerfile New MATLAB image with cleared ENTRYPOINT and libnss-wrapper for Nebari compatibility
images/README.md Updated documentation describing new image structure, local build commands, and CI workflow
.github/workflows/docker-build.yaml Refactored workflow with separate jobs for dandi (CPU/GPU variants) and matlab images
images/Dockerfile* (7 files deleted) Removed legacy Dockerfiles that don't work with Nebari
Comments suppressed due to low confidence (1)

images/dandi/Dockerfile:19

  • Downloading from the master branch without pinning to a specific commit creates a security and reproducibility risk. An attacker could compromise the repository or the file could change between builds, leading to different images from the same Dockerfile. Pin to a specific commit SHA or release tag.
RUN wget --quiet https://github.com/git-annex-remote-rclone/git-annex-remote-rclone/raw/refs/heads/master/git-annex-remote-rclone \
    && chmod +x git-annex-remote-rclone \
    && mv git-annex-remote-rclone /opt/conda/bin

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread images/dandi/Dockerfile
Comment on lines +6 to +9
-o "awscliv2.zip" \
&& unzip awscliv2.zip \
&& ./aws/install \
&& rm -rf ./aws awscliv2.zip

Copilot AI Dec 17, 2025

Copy link

Choose a reason for hiding this comment

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

The AWS CLI installation lacks verification of the download integrity. Consider adding checksum verification or using a pinned URL to a specific version to prevent supply chain attacks and ensure reproducibility.

Suggested change
-o "awscliv2.zip" \
&& unzip awscliv2.zip \
&& ./aws/install \
&& rm -rf ./aws awscliv2.zip
-o "awscli-exe-linux-x86_64.zip" \
&& curl --silent --show-error "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip.sha256" \
-o "awscli-exe-linux-x86_64.zip.sha256" \
&& sha256sum --check awscli-exe-linux-x86_64.zip.sha256 \
&& unzip awscli-exe-linux-x86_64.zip \
&& ./aws/install \
&& rm -rf ./aws awscli-exe-linux-x86_64.zip awscli-exe-linux-x86_64.zip.sha256

Copilot uses AI. Check for mistakes.
- tag: latest-nebari
build-args: ""
- tag: latest-nebari-gpu
build-args: "BASE_IMAGE=quay.io/nebari/nebari-jupyterlab-gpu:2024.11.1"

Copilot AI Dec 17, 2025

Copy link

Choose a reason for hiding this comment

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

The Nebari base image version (2024.11.1) is duplicated in both the Dockerfile default and the workflow build-args for the GPU variant. This creates a maintenance burden and risk of version drift. Consider managing the version in one place only, preferably using the ARG in the Dockerfile and letting the workflow override only when necessary.

Suggested change
build-args: "BASE_IMAGE=quay.io/nebari/nebari-jupyterlab-gpu:2024.11.1"
build-args: "BASE_IMAGE=quay.io/nebari/nebari-jupyterlab-gpu"

Copilot uses AI. Check for mistakes.
Comment thread images/dandi/Dockerfile

# fix permissions for multi-user environment
COPY postBuild /opt/dandi/postBuild
RUN /opt/dandi/postBuild

Copilot AI Dec 17, 2025

Copy link

Choose a reason for hiding this comment

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

The postBuild script is executed directly but may not have execute permissions. Add a RUN command to make it executable before running it, or invoke it through bash explicitly. For example, change line 23 to 'RUN bash /opt/dandi/postBuild' or add 'RUN chmod +x /opt/dandi/postBuild' before line 23.

Suggested change
RUN /opt/dandi/postBuild
RUN bash /opt/dandi/postBuild

Copilot uses AI. Check for mistakes.
Comment on lines +6 to +8
- rclone
- pip:
- datalad

Copilot AI Dec 17, 2025

Copy link

Choose a reason for hiding this comment

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

Dependencies lack version pins, which can lead to non-reproducible builds and potential breakage when upstream packages release breaking changes. Consider pinning at least major versions for rclone and datalad to ensure consistent builds.

Suggested change
- rclone
- pip:
- datalad
- rclone=1
- pip:
- datalad>=1,<2

Copilot uses AI. Check for mistakes.
Comment thread images/matlab/Dockerfile Outdated

USER root

# Install libnss_wrapper for Nebari user identity handling

Copilot AI Dec 17, 2025

Copy link

Choose a reason for hiding this comment

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

The comment contains a typo: 'libnss_wrapper' should use a hyphen instead of underscore for consistency with the actual package name 'libnss-wrapper' installed on line 7.

Copilot uses AI. Check for mistakes.
Comment thread images/dandi/Dockerfile
Comment on lines +17 to +19
RUN wget --quiet https://github.com/git-annex-remote-rclone/git-annex-remote-rclone/raw/refs/heads/master/git-annex-remote-rclone \
&& chmod +x git-annex-remote-rclone \
&& mv git-annex-remote-rclone /opt/conda/bin

Copilot AI Dec 17, 2025

Copy link

Choose a reason for hiding this comment

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

The wget of git-annex-remote-rclone from refs/heads/master introduces a supply chain risk because it pulls an executable directly from a mutable branch head without any pinning or integrity verification. If the upstream repository or its branch is compromised, a malicious binary could be delivered and later executed inside user sessions with access to data and credentials. To reduce this risk, download a specific tagged release or commit (or use a packaged distribution) and verify its integrity (e.g., by checksum or signature) before installing it into PATH.

Copilot uses AI. Check for mistakes.

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.

FWIW, unless someone requests, I do not think we really need git-annex-remote-rclone here. Moreover rclone has a builtin git-annex special remote now (as of v1.67.0) so if you get that fresh rclone -- might (didn't test) be set already!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I constructed this from the modifications that @satra made to the base nebari image. https://github.com/dandi/nebari-docker-images/blob/enh/dandi/Dockerfile#L165

Not really sure why we need whats in there. I'm happy to remove, just wanted to start from "parity"

@asmacdo asmacdo marked this pull request as draft December 18, 2025 17:09
@asmacdo asmacdo marked this pull request as ready for review February 9, 2026 18:47
@asmacdo asmacdo merged commit 4f62f9f into main Feb 9, 2026
4 checks passed
@asmacdo asmacdo deleted the nebari-images branch February 9, 2026 18:48
@vijayiyer05

Copy link
Copy Markdown

Noting for posterity: PRs #284 & #290 refined ("patched") this major milestone PR wrt the MATLAB image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Update MATLAB image Investigate how to build larger images Docker images (GPU, MATLAB, GPU+MATLAB) are failing to build

5 participants