Commit graph

5 commits

Author SHA1 Message Date
danielhanchen
e8ac40fa5b docker/studio: deterministic Studio install inside the image build
Two failures from the first in-image Studio install, both rooted in
install.sh probing the build host:

1. setup.sh aborted on the pre-linked llama.cpp dir: 'already exists and
   is not marked as a Studio-owned llama.cpp install'. The dir is the
   image's baked prebuilt, provisioned exclusively for Studio, so write
   the .unsloth-studio-owned marker next to the binaries.

2. With no GPU and no nvidia-smi in the build container, install.sh fell
   back to cu126 torch wheels for the Studio venv (and would pick cpu
   wheels on a CI runner without /proc/driver/nvidia), so the published
   image's Studio venv would depend on which host built it and could not
   train on Blackwell. get_torch_index_url now honours an explicit
   UNSLOTH_TORCH_INDEX_FAMILY override naming the index leaf (cu128,
   cu130, rocm7.2, cpu, ...). The resolved family flows into
   UNSLOTH_TORCH_BACKEND, which install_python_stack.py already consumes,
   so the whole downstream chain follows the pin. Dockerfile.studio sets
   cu128 on amd64 and cu130 on arm64 (DGX Spark / Grace).
2026-06-12 05:06:51 +00:00
danielhanchen
f1a63db6fa docker: ship Jupyter, Studio and prebuilt llama.cpp out of the box
Base image (docker/Dockerfile):
- Install JupyterLab + notebook + ipywidgets in a separate pure-Python uv
  pass so the cu128 pin set cannot move; EXPOSE 8888.
- Bake the prebuilt llama.cpp bundle into /opt/unsloth/llama.cpp at the
  runtime stage using studio/install_llama_prebuilt.py from the same
  UNSLOTH_REF (sha256-verified, portable CUDA bundle since the build host
  has no GPU; arm64 resolves the linux-arm64-cuda13 bundle). Export
  UNSLOTH_LLAMA_CPP_PATH so unsloth_zoo's save_pretrained_gguf finds it
  and never reaches the interactive install prompt or a source build.
- Optional github_token BuildKit secret for the resolver's API calls on
  shared CI runner IPs.

Entrypoint: UNSLOTH_ALLOW_CPU=1 degrades a missing GPU to a warning so
Docker Desktop on macOS / Windows-without-WSL2-GPU and plain CPU hosts can
run Jupyter, GGUF tooling and Studio chat; with a GPU visible the normal
pre-flight still runs.

Full image (docker/Dockerfile.studio): now mirrors the production service
set under supervisord - Studio on 8000, JupyterLab on 8888, key-only sshd
on 22 (enabled only when PUBLIC_KEY/SSH_KEY is set). Points Studio's
llama.cpp dir at the baked bundle to skip a duplicate download, accepts
any git ref via fetch+checkout (CI passes commit SHAs), and FROMs a
digest-pinned BASE_IMAGE.

Publish workflow: base image moves to the base-* tag namespace; new
build-studio/merge-studio jobs publish the full image as :latest (hub
parity with the previous production image, which shipped Studio + Jupyter
+ SSH). Studio builds FROM the exact base manifest digest published by the
same run. GPU smoke job now also boots the full image and probes Studio
/api/health and Jupyter /api.

run.sh: UNSLOTH_GPUS=none, UNSLOTH_ALLOW_CPU forwarding, UNSLOTH_PORTS
publish flags, CPU-mode and Jupyter usage examples.
2026-06-12 05:06:51 +00:00
danielhanchen
0d574d8161 Address reviewer-2 findings on PR #5748
Round-2 of the 12-persona reviewer.py pass found 17 issues. Address the
P1s + the regression-class P2s in this commit; the remaining nits are
left for a follow-up cleanup pass.

1. unsloth/_gpu_init.py: the `NVIDIA_VISIBLE_DEVICES in os.environ` check
   triggered for every NVIDIA-runtime container including `--gpus all`
   (NVIDIA_VISIBLE_DEVICES=all is the default). Gate strictly on a
   non-special device list. Also drop the precondition that the env var
   was absent: if the user already pinned TORCHINDUCTOR_COMPILE_THREADS=1
   we should still plant the UNSLOTH_FORCE_SINGLE_COMPILE_WORKER sentinel
   so the zoo-side patch knows to preserve the forcing.

2. unsloth/_gpu_init.py: after the post-`import unsloth_zoo` reassertion,
   monkey-patch `unsloth_zoo.temporary_patches.common.determine_compile_threads`
   to return 1, so any later `torch.compile` call that rebuilds the
   options dict still sees the single-worker forcing even if a downstream
   patch_torch_compile pops the env var again.

3. docker/Dockerfile: torchaudio==2.11.0 mismatched the torch==2.10.0
   release pairing; pin to 2.10.0 so the ABI is correct and the audio
   stack matches torch/cu128.

4. docker/Dockerfile: drop `12.1+PTX` from TORCH_CUDA_ARCH_LIST. The
   cu128 toolkit compiler does not know about compute_121; the trailing
   PTX entry forced nvcc to emit a `sm_121` gencode that breaks any
   in-container source builds.

5. docker/smoke_test.py: the device-capability floor said `cap[0] < 8`,
   rejecting Turing (sm_75) while the Dockerfile + entrypoint advertise
   sm_75 as supported. Lower the smoke floor to sm_75 and print a hint
   that bf16 is not available on Turing.

6. docker/run.sh: `-it` is unconditional; CI / non-TTY invocations died
   with "the input device is not a TTY". Probe `[ -t 0 ] && [ -t 1 ]`
   first. Also remove `set -x` which echoed the forwarded HF_TOKEN /
   WANDB_API_KEY / UNSLOTH_LICENSE values to stdout.

7. docker/test_locally.sh: `-e HF_TOKEN="${HF_TOKEN:-}"` either pasted
   the secret verbatim into the process arg list or shadowed any
   in-container value with an empty string. Forward conditionally.

8. .github/workflows/docker-publish.yml: gate `latest` on default branch
   AND on `unsloth_ref` not being overridden via workflow_dispatch.
   Otherwise a maintainer testing a feature SHA from main could overwrite
   `:latest` with non-main source.

9. docker/Dockerfile.studio: add an `UNSLOTH_STUDIO_REF` build-arg so
   the Studio companion image is pinned to a known unsloth ref instead
   of cloning `main` whenever it builds.
2026-05-24 15:24:20 +00:00
danielhanchen
291e2cfabb docker/Dockerfile.studio: keep source for the editable install
install.sh --local installs unsloth into the Studio venv as an editable
package keyed to the just-cloned source tree. We were rm-rf'ing that
tree in the same RUN; the resulting `unsloth_cli` import then failed at
container start with `ModuleNotFoundError: No module named 'unsloth_cli'`.

Clone the source directly under UNSLOTH_STUDIO_HOME/src so it persists
in the image layer, and strip only .git to save ~120MB.
2026-05-24 14:08:45 +00:00
danielhanchen
a01fa21e91 docker: add Dockerfile.studio extending the Blackwell image with Unsloth Studio
The base unsloth-blackwell image ships the `unsloth` CLI but refuses to
start `unsloth studio` until the dedicated Studio venv is laid down under
UNSLOTH_STUDIO_HOME by install.sh. Build it once and commit the result as
an opt-in companion tag (`:studio`) instead of bloating the base image.

Build:
  docker buildx build --build-arg BASE_TAG=test \
    -f docker/Dockerfile.studio -t unsloth-blackwell:studio docker/

Run:
  docker run --rm --gpus '"device=0"' -p 8888:8888 unsloth-blackwell:studio

Open http://localhost:8888. Inference (llama.cpp CPU + GPU) and training
are both available. First-boot admin password lands in container logs
and at /opt/unsloth-studio/auth/.bootstrap_password.
2026-05-24 14:00:43 +00:00