train.sh imports. That is all.
What belongs in the image
Logs:
print, logging, and framework stdout/stderr go to the console log tab. Do not POST /api/ingest/logs.
Curves: not parsed from stdout. Call starforge.report from training code.
A starting Dockerfile
This matches the style of the platform TRL image: CUDA devel base, a venv onPATH, no StarForge package required if you will install the wheel in a later RUN (recommended for catalog custom/custom).
train.py imports. If you need DeepSpeed JIT compile, a devel image (nvcc) is the usual requirement, same as Dockerfile.trl.
local executor runs the entrypoint with bash. PATH must still point at that venv so python inside train.sh is not /usr/bin/python without torch.
Build and push
Allowlist
--image is parsed for a registry host (ghcr.io, localhost:5000, docker.io when the name has no host). That host must appear in the server list FORGE_ALLOWED_IMAGE_REGISTRIES (comma-separated hostnames in .env).
Operators: set something like
FORGE_ALLOWED_IMAGE_REGISTRIES=registry.example.com,ghcr.io. Nodes must be able to pull (KubeRay imagePullSecrets, agent Docker login, Slurm enroot/SIF already converted).
Executor notes
If pull is slow, the job sits in
PENDING until the preRunning deadline, then FAILED. That is not a training bug.
Do not
- COPY the StarForge source tree into
/optand hope it matches the server’s runner. The capsule is content-addressed and injected. - Bake
HF_TOKENinto a layer. The server injectsHF_TOKEN/HUGGING_FACE_HUB_TOKENwhen configured, or a secrets file path (CLUSTER_SECRETS_FILE). - Point
FORGE_INGEST_URLat127.0.0.1on the console host. Training nodes cannot use your laptop loopback. That variable is server-side; submitters do not set it, but empty charts with healthy stdout usually mean ops got it wrong.