Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c9ff52b
docker: Colab-grade JupyterLab and Studio UX for the Blackwell image
danielhanchen Jun 25, 2026
7b5bb24
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 25, 2026
e496095
docker: address review feedback on the JupyterLab/Studio UX
danielhanchen Jun 26, 2026
50f7170
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 26, 2026
b963403
docker: publish lean image as :core and full image as :studio
danielhanchen Jun 26, 2026
dde7a26
docker: address second-round review feedback on the JupyterLab/Studio UX
danielhanchen Jun 26, 2026
2eba8a4
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 26, 2026
30e7e09
Merge remote-tracking branch 'origin/docker-blackwell-build' into pr-…
danielhanchen Jun 26, 2026
9a53256
docker: keep Studio branding RUN free of comments inside the line con…
danielhanchen Jun 26, 2026
a56a7a8
Merge remote-tracking branch 'origin/docker-blackwell-build' into pr-…
danielhanchen Jun 26, 2026
2e4699c
Merge remote-tracking branch 'origin/docker-blackwell-build' into pr-…
danielhanchen Jun 26, 2026
38f1115
Merge remote-tracking branch 'origin/docker-blackwell-build' into pr-…
danielhanchen Jun 26, 2026
6fd9744
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 26, 2026
3fb8804
docker: AGPLv3 attribution + integrity guard for the Studio/JupyterLa…
danielhanchen Jun 27, 2026
d1a5b58
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 27, 2026
9cd1951
Merge remote-tracking branch 'origin/docker-blackwell-build' into pr-…
danielhanchen Jun 27, 2026
2482719
docker: address #6681 review round 2 (colab magics, output select, br…
danielhanchen Jun 27, 2026
0a8ae80
Merge remote-tracking branch 'origin/pr-jupyter-studio-ux' (pre-commi…
danielhanchen Jun 27, 2026
2c190aa
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 27, 2026
04452eb
labext: pin JupyterLab extension deps; confirm.ps1 /login probe
danielhanchen Jun 29, 2026
67c0a8e
Merge remote-tracking branch 'origin/docker-blackwell-build' into HEAD
danielhanchen Jul 5, 2026
5d41a03
docker: categorize AMD/domain notebooks and wire the feature validati…
danielhanchen Jul 5, 2026
38df387
labext: use caret ranges so jlpm dedups JupyterLab/Lumino singletons
danielhanchen Jul 5, 2026
b558bc7
ci(studio-backend): trigger on docker/** so the JupyterLab feature va…
danielhanchen Jul 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 19 additions & 16 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ jobs:
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-base-${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }}
name: digests-core-${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
Expand All @@ -289,7 +289,7 @@ jobs:
- uses: actions/download-artifact@v4
with:
path: /tmp/digests
pattern: digests-base-*
pattern: digests-core-*
merge-multiple: true

- uses: docker/setup-buildx-action@v3
Expand All @@ -310,17 +310,17 @@ jobs:
# and collide with the Studio image that legitimately owns :latest.
flavor: latest=false
tags: |
# The lean training image publishes under the base- prefix; the
# The lean training image publishes under the core- prefix; the
# full Studio image (build-studio/merge-studio below) owns
# :latest, matching what the previous production image shipped.
# Only tag :base when the workflow ran on the default branch
# Only tag :core when the workflow ran on the default branch
# AND the operator did NOT override unsloth_ref on dispatch.
# Without the second condition a maintainer testing a feature
# SHA from main could overwrite :base with non-main source.
type=raw,value=base,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && github.event.inputs.unsloth_ref == '' }}
type=ref,event=tag,prefix=base-
type=schedule,pattern=base-nightly
type=sha,prefix=base-sha-,format=short
# SHA from main could overwrite :core with non-main source.
type=raw,value=core,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && github.event.inputs.unsloth_ref == '' }}
type=ref,event=tag,prefix=core-
type=schedule,pattern=core-nightly
type=sha,prefix=core-sha-,format=short

- name: Create multi-arch manifest
working-directory: /tmp/digests
Expand Down Expand Up @@ -477,8 +477,10 @@ jobs:
flavor: latest=false
tags: |
# The full Studio image owns the unprefixed namespace, headed by
# :latest (default branch only). Tag pushes publish the version tag.
# :latest plus a stable :studio alias (default branch only). Tag
# pushes publish the version tag. Same gating rationale as the core job.
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && github.event.inputs.unsloth_ref == '' }}
type=raw,value=studio,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && github.event.inputs.unsloth_ref == '' }}
type=ref,event=tag
type=schedule,pattern=nightly
type=sha,prefix=sha-,format=short
Expand Down Expand Up @@ -529,19 +531,19 @@ jobs:
# tag list the merge step pushed, so the smoke test pulls the right ref).
flavor: latest=false
tags: |
type=raw,value=base,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && github.event.inputs.unsloth_ref == '' }}
type=ref,event=tag,prefix=base-
type=schedule,pattern=base-nightly
type=sha,prefix=base-sha-,format=short
type=raw,value=core,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && github.event.inputs.unsloth_ref == '' }}
type=ref,event=tag,prefix=core-
type=schedule,pattern=core-nightly
type=sha,prefix=core-sha-,format=short

- name: Pull and smoke-test the base image
run: |
# Use the first tag from the metadata output -- that is the image we
# just published. Falls back to :base only when the metadata is
# just published. Falls back to :core only when the metadata is
# empty (defensive; should not happen on default-branch runs).
TAG="$(jq -r '.tags[0] // ""' <<<"$STEPS_META_BASE_JSON")"
if [ -z "$TAG" ]; then
TAG="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:base"
TAG="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:core"
fi
echo "smoke-testing $TAG"
docker pull "$TAG"
Expand All @@ -559,6 +561,7 @@ jobs:
flavor: latest=false
tags: |
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && github.event.inputs.unsloth_ref == '' }}
type=raw,value=studio,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && github.event.inputs.unsloth_ref == '' }}
type=ref,event=tag
type=schedule,pattern=nightly
type=sha,prefix=sha-,format=short
Expand Down
11 changes: 11 additions & 0 deletions .github/workflows/studio-backend-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ on:
- 'unsloth/**'
- 'unsloth_cli/**'
- 'tests/**'
# The "Docker JupyterLab/notebook feature validation" step below runs
# tests/validate_studio_features.py, which checks docker/jupyter (the
# labextension, overrides.json, login branding) and the docker notebook
# helpers. Without docker/** here a docker-only change skips that guard.
- 'docker/**'
- 'pyproject.toml'
- '.github/workflows/studio-backend-ci.yml'
push:
Expand Down Expand Up @@ -238,3 +243,9 @@ jobs:
echo "::endgroup::"
done

- name: Docker JupyterLab/notebook feature validation
# Named validate_studio_features.py (not test_*.py) so pytest's default
# discovery skips it; run it explicitly here so a regression in the
# notebook view, Colab compat, strip, JupyterLab defaults or login
# branding fails CI instead of only when someone runs it by hand.
run: python tests/validate_studio_features.py
Comment on lines +246 to +251

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Add docker paths to the validation workflow

For PRs that only change the Docker/Jupyter files this step is meant to validate, it will not run: the workflow's pull_request.paths filter includes studio/**, unsloth/**, tests/**, etc., but not docker/**. I checked this same workflow, so a regression in docker/jupyter/overrides.json, the labextension, or the notebook helpers can still pass PR CI unless the PR also happens to touch tests/** or the workflow file.

Useful? React with 👍 / 👎.

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.

Good catch. Added docker/** to the pull_request paths in b558bc7 so the Docker JupyterLab/notebook feature validation runs on docker-only changes.

20 changes: 20 additions & 0 deletions docker/.dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,23 @@
!unsloth_run.py
!unsloth_sync_notebooks.sh
!unsloth_nb_content_sig.py
!unsloth_nb_view.py
!unsloth_nb_strip_colab.py
!unsloth_colab_compat.py
!jupyter
!jupyter/unsloth_branding.py
!jupyter/jupyter_server_config.d
!jupyter/jupyter_server_config.d/**
!jupyter/overrides.json
!jupyter/favicon.ico
!jupyter/logo.png
!jupyter/login.html
Comment on lines +25 to +28

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Include the sticker installer in the Docker build context

When building Dockerfile.studio with docker/ as the context, this allowlist still excludes jupyter/install_sloth_stickers.py because the file is not whitelisted after the top-level ** ignore. The new COPY jupyter/install_sloth_stickers.py ... in the studio Dockerfile therefore fails with a missing source before the image can build; add an exception for that helper alongside the other jupyter/ assets.

Useful? React with 👍 / 👎.

!jupyter/install_sloth_stickers.py
!jupyter/unsloth_labext
!jupyter/unsloth_labext/package.json
!jupyter/unsloth_labext/tsconfig.json
!jupyter/unsloth_labext/.yarnrc.yml
!jupyter/unsloth_labext/src
!jupyter/unsloth_labext/src/**
!jupyter/unsloth_labext/style
!jupyter/unsloth_labext/style/**
9 changes: 6 additions & 3 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -672,21 +672,24 @@ RUN mkdir -p ${HF_HOME} ${TRITON_CACHE_DIR}
# * unsloth-run: headless `unsloth-run <notebook|url>` that auto-picks the
# sidecar and executes every cell -- the robust driven path.
# ---------------------------------------------------------------------------
COPY unsloth_nb_compat.py unsloth_pip_shim.py unsloth_nb_pip_magic.py unsloth_ipython_startup.py unsloth_run.py unsloth_sync_notebooks.sh unsloth_nb_content_sig.py /opt/unsloth-nb/
COPY unsloth_nb_compat.py unsloth_pip_shim.py unsloth_nb_pip_magic.py unsloth_ipython_startup.py unsloth_run.py unsloth_sync_notebooks.sh unsloth_nb_content_sig.py unsloth_nb_view.py unsloth_nb_strip_colab.py unsloth_colab_compat.py /opt/unsloth-nb/
RUN set -eux \
&& SP=/opt/unsloth-venv/lib/python${PYTHON_VERSION}/site-packages \
&& cp /opt/unsloth-nb/unsloth_nb_compat.py "$SP/unsloth_nb_compat.py" \
&& cp /opt/unsloth-nb/unsloth_nb_pip_magic.py "$SP/unsloth_nb_pip_magic.py" \
&& chmod +x /opt/unsloth-nb/unsloth_pip_shim.py /opt/unsloth-nb/unsloth_run.py /opt/unsloth-nb/unsloth_sync_notebooks.sh /opt/unsloth-nb/unsloth_nb_content_sig.py \
&& cp /opt/unsloth-nb/unsloth_colab_compat.py "$SP/unsloth_colab_compat.py" \
&& chmod +x /opt/unsloth-nb/unsloth_pip_shim.py /opt/unsloth-nb/unsloth_run.py /opt/unsloth-nb/unsloth_sync_notebooks.sh /opt/unsloth-nb/unsloth_nb_content_sig.py /opt/unsloth-nb/unsloth_nb_view.py /opt/unsloth-nb/unsloth_nb_strip_colab.py \
&& mkdir -p /opt/unsloth-nb/bin \
&& for t in pip pip3 uv; do ln -sf /opt/unsloth-nb/unsloth_pip_shim.py /opt/unsloth-nb/bin/$t; done \
&& ln -sf /opt/unsloth-nb/unsloth_run.py /usr/local/bin/unsloth-run \
&& ln -sf /opt/unsloth-nb/unsloth_sync_notebooks.sh /usr/local/bin/unsloth-sync-notebooks \
&& ln -sf /opt/unsloth-nb/unsloth_nb_content_sig.py /usr/local/bin/unsloth-nb-content-sig \
&& ln -sf /opt/unsloth-nb/unsloth_nb_view.py /usr/local/bin/unsloth-nb-view \
&& ln -sf /opt/unsloth-nb/unsloth_nb_strip_colab.py /usr/local/bin/unsloth-nb-strip-colab \
&& mkdir -p /opt/unsloth-nb/ipython/profile_default/startup \
&& cp /opt/unsloth-nb/unsloth_ipython_startup.py /opt/unsloth-nb/ipython/profile_default/startup/00-unsloth-nb.py \
&& chmod -R a+rX /opt/unsloth-nb/ipython \
&& /opt/unsloth-venv/bin/python -c "import sys, glob; sys.path.insert(0, '$SP'); import unsloth_nb_compat; print('nb-compat OK; baked sidecars:', sorted(glob.glob('/opt/unsloth-venv/tf-sidecars/t_*')))"
&& /opt/unsloth-venv/bin/python -c "import sys, glob; sys.path.insert(0, '$SP'); import unsloth_nb_compat, unsloth_colab_compat; print('nb-compat OK; baked sidecars:', sorted(glob.glob('/opt/unsloth-venv/tf-sidecars/t_*')))"
# Shim dir AHEAD of the venv bin so `!pip`/`!uv` resolve to the shim, not the real tool.
ENV PATH=/opt/unsloth-nb/bin:${PATH}
# Load the notebook startup hook (sidecar activation + %pip/%uv magic re-point)
Expand Down
90 changes: 87 additions & 3 deletions docker/Dockerfile.studio
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# Full Unsloth image: base training stack + Studio + JupyterLab + sshd.
#
# This is the image published as docker.io/unsloth/unsloth:latest. It layers
# Unsloth Studio on top of the lean base image (Dockerfile, published under
# the `base` tags) and runs the same service trio as the previous production
# This is the image published as docker.io/unsloth/unsloth:studio (and the
# default :latest). It layers Unsloth Studio on top of the lean core image
# (Dockerfile, published under the `core` tags) and runs the same service trio
# as the previous production
# image: Studio on 8000, JupyterLab on 8888, key-only sshd on 22.
#
# Build (local):
Expand All @@ -28,6 +29,27 @@
# images always ship the same stack.

ARG BASE_IMAGE=unsloth-blackwell:test

# --- builder stage: prebuild the Unsloth JupyterLab extension -----------------
# Builds the named "Unsloth Dark" (Monokai) theme + the Colab-style Down/Up
# cell-navigation keymap. Node lives ONLY in this throwaway stage; the final
# image copies just the prebuilt static labextension, so the runtime stays
# Node-free. Uses the base image's bundled jlpm + jupyterlab (version-matched).
FROM ${BASE_IMAGE} AS labext-builder
ENV DEBIAN_FRONTEND=noninteractive
# JupyterLab 4.6's build tooling declares a Node >=20 engine; Ubuntu 24.04's
# distro nodejs is 18, so pull Node 20 LTS from NodeSource (it bundles npm).
# This stage is thrown away, so the extra apt sources never reach the runtime.
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates curl gnupg git \
&& curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
&& apt-get install -y --no-install-recommends nodejs \
&& rm -rf /var/lib/apt/lists/*
Comment on lines +43 to +47

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Install a Node version that can build JupyterLab 4.6

On the Ubuntu 24.04 CUDA base, apt-get install nodejs resolves to Node 18, but the JupyterLab 4.6 JavaScript packages used by the next jlpm install declare a Node >=20 engine. In a clean studio build this makes the labextension builder fail before producing /opt/labext-src/unsloth-jupyterlab/labextension; install/pin a Node 20+ source instead of the distro nodejs package.

Useful? React with 👍 / 👎.

COPY jupyter/unsloth_labext /opt/labext-src
RUN cd /opt/labext-src \
&& /opt/unsloth-venv/bin/jlpm install \
&& /opt/unsloth-venv/bin/jlpm build:prod

FROM ${BASE_IMAGE}

# Studio source ref to clone. Defaults to `main`, but a CI publish pipeline
Expand Down Expand Up @@ -176,6 +198,68 @@ COPY fetch_llama_prebuilt.py /usr/local/lib/unsloth/fetch_llama_prebuilt.py
# Optional public Cloudflare tunnel for JupyterLab (UNSLOTH_JUPYTER_CLOUDFLARE=1,
# or `unsloth-jupyter-tunnel --force`); supervisord runs it as jupyter-cloudflare.
COPY unsloth_jupyter_tunnel.sh /usr/local/bin/unsloth-jupyter-tunnel
# JupyterLab defaults baked for every container: the named "Unsloth Dark"
# (Monokai) theme with adaptive light/dark by system preference, a per-cell run
# button that does NOT auto-advance, a labeled "Restart & Run All", windowing
# disabled so collapsing a long output does not snap to the cell top,
# ArrowDown/Up jumping to the TOP of the next/previous cell, and the official
# Jupyter "get notified about news" prompt suppressed (fetchNews/checkForUpdates
# off). overrides.json is the system-wide settings override (read from the base
# venv's share/jupyter/lab/settings); the theme + keymap + Unsloth top-bar logo
# ship as the prebuilt labextension built in the labext-builder stage above.
COPY jupyter/overrides.json /opt/unsloth-venv/share/jupyter/lab/settings/overrides.json
COPY --from=labext-builder /opt/labext-src/unsloth-jupyterlab/labextension /opt/unsloth-venv/share/jupyter/labextensions/unsloth-jupyterlab
# Unsloth branding (all served by jupyter_server, so applied to its site-packages
# the same way): replace the browser-tab favicon and the page logo with the
# Unsloth logo, and brand the login screen (dark Unsloth-themed login.html).
# Also disable + lock the stock top-left Jupyter logo plugin so the Unsloth logo
# widget shipped by the labextension is the only one rendered in the top bar
# (lock keeps users from re-enabling it in the UI).
# The sloth-sticker install is the ONLY fail-soft branding step: it is scoped to
# its own { ...; } group with a `|| echo` fallback below, so a missing Studio
# "Sloth emojis" folder does not break the build, while the REQUIRED steps above
# it (JS resolve, favicon/logo/login copy) stay fatal. (The comment is kept out
# of the RUN body so no comment line sits inside a backslash continuation, which
# some Dockerfile parsers choke on.) login.html's onerror falls back to the
# Unsloth logo if the sticker dir is ever absent.
COPY jupyter/favicon.ico /tmp/unsloth-branding/favicon.ico
COPY jupyter/logo.png /tmp/unsloth-branding/logo.png
COPY jupyter/login.html /tmp/unsloth-branding/login.html
COPY jupyter/install_sloth_stickers.py /tmp/unsloth-branding/install_sloth_stickers.py
RUN JS="$(/opt/unsloth-venv/bin/python -c 'import os, jupyter_server; print(os.path.dirname(jupyter_server.__file__))')" \
&& for n in favicon.ico favicon-notebook.ico favicon-file.ico favicon-terminal.ico; do \
cp /tmp/unsloth-branding/favicon.ico "${JS}/static/favicons/${n}"; \
done \
&& cp /tmp/unsloth-branding/logo.png "${JS}/static/logo/logo.png" \
&& cp /tmp/unsloth-branding/login.html "${JS}/templates/login.html" \
&& { /opt/unsloth-venv/bin/python /tmp/unsloth-branding/install_sloth_stickers.py \
--src "${UNSLOTH_STUDIO_HOME}/src/studio/frontend/public/Sloth emojis" \
--dest "${JS}/static/sloth" \
|| echo ">> sloth stickers not installed (login falls back to the Unsloth logo)"; } \
&& rm -rf /tmp/unsloth-branding \
&& /opt/unsloth-venv/bin/jupyter labextension disable @jupyterlab/application-extension:logo \
&& /opt/unsloth-venv/bin/jupyter labextension lock @jupyterlab/application-extension:logo \
&& /opt/unsloth-venv/bin/jupyter labextension disable @jupyterlab/apputils-extension:splash \
&& /opt/unsloth-venv/bin/jupyter labextension lock @jupyterlab/apputils-extension:splash \
&& /opt/unsloth-venv/bin/jupyter labextension lock unsloth-jupyterlab
# Branding integrity guard: the canonical attribution checker (also a
# jupyter_server extension), the full AGPLv3 license text, and the config that
# enables the extension. Installed into the base venv so it is on the jupyter
# process's import + config search path. The stock @apputils-extension:splash is
# disabled+locked above so the labextension's spinning-logo splash is the sole
# ISplashScreen provider. The build-time --verify FAILS the image build if any
# Unsloth attribution / license asset is missing or altered.
COPY jupyter/unsloth_branding.py /tmp/unsloth-branding-guard/unsloth_branding.py
COPY jupyter/jupyter_server_config.d/unsloth_branding_guard.json /tmp/unsloth-branding-guard/unsloth_branding_guard.json
RUN SP="$(/opt/unsloth-venv/bin/python -c 'import sysconfig; print(sysconfig.get_path("purelib"))')" \
&& cp /tmp/unsloth-branding-guard/unsloth_branding.py "${SP}/unsloth_branding.py" \
&& mkdir -p /opt/unsloth-venv/etc/jupyter/jupyter_server_config.d \
&& cp /tmp/unsloth-branding-guard/unsloth_branding_guard.json \
/opt/unsloth-venv/etc/jupyter/jupyter_server_config.d/unsloth_branding_guard.json \
&& cp "${UNSLOTH_STUDIO_HOME}/src/studio/LICENSE.AGPL-3.0" \
/opt/unsloth-venv/share/jupyter/UNSLOTH_LICENSE.AGPL-3.0 \
&& rm -rf /tmp/unsloth-branding-guard \
&& /opt/unsloth-venv/bin/python -m unsloth_branding --verify
RUN chmod +x /usr/local/bin/unsloth-studio-launch \
/usr/local/bin/unsloth-studio-update \
/usr/local/bin/unsloth-llama-update \
Expand Down
2 changes: 1 addition & 1 deletion docker/docker_confirm.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

$ErrorActionPreference = "Continue"
$IMAGE = if ($env:IMAGE) { $env:IMAGE } else { "unsloth/unsloth:latest" }
$BASE_IMAGE = if ($env:BASE_IMAGE) { $env:BASE_IMAGE } else { "unsloth/unsloth:base" }
$BASE_IMAGE = if ($env:BASE_IMAGE) { $env:BASE_IMAGE } else { "unsloth/unsloth:core" }
$GPUS = if ($env:GPUS) { $env:GPUS } else { "auto" }
$PORT_STUDIO = if ($env:PORT_STUDIO) { $env:PORT_STUDIO } else { 18000 }
$PORT_JUPYTER = if ($env:PORT_JUPYTER) { $env:PORT_JUPYTER } else { 18888 }
Expand Down
4 changes: 2 additions & 2 deletions docker/docker_confirm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
# Studio chat / Jupyter / GGUF tooling still validate.
#
# Env overrides: IMAGE (default unsloth/unsloth:latest)
# BASE_IMAGE (default unsloth/unsloth:base)
# BASE_IMAGE (default unsloth/unsloth:core)
# GPUS=all|none|0|0,1 (default: auto-detect)
# PORT_STUDIO=18000 PORT_JUPYTER=18888
# WORK=~/unsloth_docker_test (logs)
Expand All @@ -33,7 +33,7 @@
set -uo pipefail

IMAGE="${IMAGE:-unsloth/unsloth:latest}"
BASE_IMAGE="${BASE_IMAGE:-unsloth/unsloth:base}"
BASE_IMAGE="${BASE_IMAGE:-unsloth/unsloth:core}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Publish the tag used by confirmation scripts

This default now pulls unsloth/unsloth:core, but the in-repo publish workflow still creates only :base and base-* tags (.github/workflows/docker-publish.yml lines 228-238 and 432-435) and never creates a :core tag. On fresh user machines the confirmation scripts therefore fail in the pull phase unless BASE_IMAGE is overridden; update the workflow tags too, or keep the scripts on the published tag.

Useful? React with 👍 / 👎.

GPUS="${GPUS:-auto}"
PORT_STUDIO="${PORT_STUDIO:-18000}"
PORT_JUPYTER="${PORT_JUPYTER:-18888}"
Expand Down
Binary file added docker/jupyter/favicon.ico
Binary file not shown.
Loading
Loading