Skip to main content

Base image

The ssh and jupyter launch modes need an image that ships an SSH server, JupyterLab and the on-start contract. A plain upstream image such as pytorch/pytorch ships none of that, which is why those two modes are restricted to images derived from the Superheat base.

superheat/base

That is the canonical name, on Docker Hub. The image is also mirrored to ghcr.io/superheat-software/base with an identical set of tags, pushed by the same build — so either reference works, and hosts fall back to the mirror if Docker Hub is unreachable. Prefer the short name.

Both are public, so hosts pull without credentials and you do not need registry credentials on a template that uses the base.

Published tags

TagWhat it is
cuda-12.1CUDA 12.1
cuda-12.4CUDA 12.4
cuda-12.6CUDA 12.6
cuda-12.8CUDA 12.8
latestthe newest CUDA minor
sha-<12 chars>-<minor>one immutable tag per build and CUDA minor

Each cuda-<minor> tag is built from the matching NVIDIA CUDA cuDNN runtime image on Ubuntu 22.04 — cuda-12.4 from nvidia/cuda:12.4.1-cudnn-runtime-ubuntu22.04. Images are amd64 only, which matches the fleet: Superheat hosts are x86_64.

The cuda-<minor> naming is also what the [Automatic] template tag resolves against. Leaving a template's tag as [Automatic] picks the newest tag whose CUDA the chosen machine can run, so one template works across a fleet with mixed drivers. Pin a specific tag when you need a build to be reproducible rather than current.

What it adds

On top of the CUDA runtime: openssh-server, python3 with pip and jupyterlab, tini, gosu, openssl, ca-certificates, curl, git and rsync. The working directory is /workspace and the entrypoint is tini -- /opt/superheat/entrypoint.sh.

The image carries the label com.superheat.base="true". That label is how Superheat recognizes an image as usable for ssh and jupyter modes, and it is inherited by anything you build FROM the base.

What the entrypoint does

Every step is idempotent, so stopping and starting an instance re-runs it safely against the same container.

StepDetail
1. Export environmentThe container environment is written to /etc/environment and /etc/profile.d/superheat-env.sh, because sshd and Jupyter spawn login shells that do not inherit it. Provisioning secrets are excluded.
2. Install keysPUBLIC_KEY and SUPERHEAT_SSH_PUBLIC_KEYS are written to /root/.ssh/authorized_keys.
3. Start sshdHost keys are generated if missing, then sshd listens on container port 22. Key-only; passwords are not accepted.
4. Start JupyterOnly when JUPYTER_TOKEN is set. A self-signed certificate is generated once and JupyterLab is bound to 0.0.0.0:${JUPYTER_PORT} over HTTPS.
5. Run onstartSUPERHEAT_ONSTART runs once, guarded by a sentinel. A failure is logged and the container stays up.
6. Hand offThe image's CMD is executed if there is one; otherwise the container idles so it stays running for the port map.

The environment contract

These variable names are the wire between Superheat and the image. Build on the base and the entrypoint honors them for you; build your own entrypoint and these are what you have to implement.

VariablePurpose
PUBLIC_KEYA single OpenSSH public key, appended to authorized_keys
SUPERHEAT_SSH_PUBLIC_KEYSNewline-separated OpenSSH public keys, appended to authorized_keys
SUPERHEAT_ONSTARTBash run once at first start. Sensitive; not persisted to the env files. The bare alias ONSTART is also accepted
JUPYTER_TOKENWhen set, JupyterLab starts with this as its access token
JUPYTER_PORTJupyter bind port, default 8080
JUPYTER_DIRJupyter root directory, default /workspace
JUPYTER_LABtrue for JupyterLab (default), false for the classic notebook
OPEN_BUTTON_PORTInformational — the console Open button target port
CONTAINER_IDInformational — the workload identifier
GPU_COUNTInformational — how many GPUs are assigned
SUPERHEAT_TCP_PORT_<n>Informational — the published host port for container port <n>

Superheat sets these last, after your template environment and any renter overrides, so none of them can be shadowed. See Environment variables.

Building your own image

Inherit from the tag whose CUDA matches what your code needs, install your dependencies, and leave the entrypoint alone:

FROM superheat/base:cuda-12.4

RUN pip install --no-cache-dir torch torchvision transformers

COPY train.py /workspace/train.py
WORKDIR /workspace

Three rules keep the result launchable in ssh and jupyter modes:

  1. Inherit, do not rebuild. Building from nvidia/cuda and copying in your own sshd loses the com.superheat.base label and the entrypoint contract along with it.
  2. Do not override ENTRYPOINT. The base entrypoint is what starts sshd, Jupyter and your on-start script. Overriding it turns an ssh template into a container with no way in.
  3. Put your process in CMD. The entrypoint executes CMD after provisioning, so a long-running server started that way gets sshd and Jupyter alongside it.

If your image cannot follow those rules — an upstream image you do not control, or one with an entrypoint of its own — use the args launch mode instead. It runs any image's native entrypoint and needs nothing from the base. See Launch modes.

Which tag to inherit from

SituationTag
Your framework pins a CUDA minorthe matching cuda-<minor>
You want the newest available CUDA and can rebuildlatest
You need a build to resolve identically months from nowthe sha-… tag

Pinning a cuda-<minor> tag is the usual answer. latest moves when a new CUDA minor is published, which is fine for a dev image and a poor foundation for a reproducible training run.

Filesystem layout

PathContents
/workspaceThe working directory, and Jupyter's root by default
/opt/superheat/entrypoint.shThe provisioning entrypoint
/var/lib/superheat/onstart.shThe on-start body as it was executed
/var/lib/superheat/.onstart-doneThe sentinel that stops the on-start script re-running
/var/log/superheat/onstart.logOn-start output
/var/log/superheat/jupyter.logJupyter output
/etc/profile.d/superheat-env.shThe environment as login shells see it

sshd and Jupyter also stream to the container log, which is what the console shows. See Logs.