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-cn-registry.cn-shanghai.cr.aliyuncs.com/superheat/base

That is the base image's name on Superheat CN, hosted on Alibaba Cloud ACR. Write this full reference on a template: superheat/base without the ACR host fails to deploy in ssh and jupyter modes.

The repository is public and allows anonymous pulls, so hosts pull without credentials and you do not need registry credentials on a template that uses the base. The other Superheat images and the third-party images on ACR are listed in Images on Superheat CN.

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

ACR carries only these tags.

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", and anything you build FROM the base inherits it. When Superheat takes over the entrypoint, the host checks this label after the pull and before it creates the container. But what decides whether Superheat takes over the entrypoint in ssh and jupyter modes is the image reference, not the label: on Superheat CN, only images in the superheat/ namespace on ACR are taken over. See Images on Superheat CN.

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, with Jupyter's own Origin check left on.
5. Start the access proxyOnly when SUPERHEAT_ACCESS_PORTS is set. The proxy takes those ports on the container's own addresses and requires the access token on them; the entrypoint sets SUPERHEAT_APP_HOST=127.0.0.1 so the app listens behind it. See Requiring the access token.
6. Run onstartSUPERHEAT_ONSTART runs once, guarded by a sentinel. A failure is logged and the container stays up.
7. 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
SUPERHEAT_ACCESS_PORTSContainer ports the access proxy guards, comma-separated. Set by the platform for ports declared auth: proxy
SUPERHEAT_ACCESS_TOKENThe instance access token those ports require. Sensitive; not persisted to the env files
SUPERHEAT_APP_HOSTSet by the entrypoint, not read by it: 127.0.0.1 whenever SUPERHEAT_ACCESS_PORTS is set — even if the proxy cannot start, so a guarded port stays unreachable rather than open — unset otherwise. Start your app on "${SUPERHEAT_APP_HOST:-0.0.0.0}"
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-cn-registry.cn-shanghai.cr.aliyuncs.com/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 base image's entrypoint contract intact in the result:

  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. Override it and none of them start.
  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.

Push the built image to your own registry in mainland China, such as your own Alibaba Cloud ACR instance. It is not in the superheat/ namespace on ACR, so Superheat does not take over its entrypoint in ssh and jupyter modes and does not open an SSH port for it: run it in args mode and declare the ports it serves on the template. See Using your own image.

An upstream image you do not control, or one with an entrypoint of its own, also runs in args mode. args runs the 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 an identical build months from nowbuild once, push to your own registry, and pin your own tag from then on

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.