跳至主要內容

基礎映像檔

sshjupyter 啟動模式需要一個內含 SSH 伺服器、JupyterLab 與啟動時契約的映像檔。像 pytorch/pytorch 這類單純的上游映像檔完全沒有這些,這就是為什麼這兩種模式僅限使用衍生自 Superheat 基礎映像檔的映像檔。

superheat/base

這是規範名稱,託管於 Docker Hub。該映像檔同時鏡像至 ghcr.io/superheat-software/base,標籤集完全相同,由同一次建置推送 —— 因此兩種參照皆可使用,且當 Docker Hub 無法連線時主機會回退至鏡像來源。建議使用短名稱。

兩者皆為公開,所以主機不需要憑證就能拉取,使用基礎映像檔的範本也不需要填寫登錄庫憑證。

已發布的標籤

標籤內容
cuda-12.1CUDA 12.1
cuda-12.4CUDA 12.4
cuda-12.6CUDA 12.6
cuda-12.8CUDA 12.8
latest最新的 CUDA 次版本
sha-<12 chars>-<minor>每次建置搭配每個 CUDA 次版本各一個不可變標籤

每個 cuda-<minor> 標籤都是以 Ubuntu 22.04 上對應的 NVIDIA CUDA cuDNN runtime 映像檔建置的 —— cuda-12.4 來自 nvidia/cuda:12.4.1-cudnn-runtime-ubuntu22.04。映像檔只有 amd64,這與機群相符:Superheat 主機都是 x86_64。

cuda-<minor> 這套命名也是 [Automatic] 範本標籤解析時的依據。把範本的標籤留在 [Automatic],會挑出所選機器的 CUDA 能執行的最新標籤,因此同一個範本能在驅動程式版本混雜的機群上通用。當你需要的是可重現而非最新的建置時,請釘選特定標籤。

它額外加了什麼

在 CUDA runtime 之上:openssh-server、附帶 pipjupyterlabpython3tinigosuopensslca-certificatescurlgitrsync。工作目錄是 /workspace,進入點是 tini -- /opt/superheat/entrypoint.sh

這個映像檔帶有 com.superheat.base="true" 標籤。Superheat 就是靠這個標籤辨識一個映像檔可用於 sshjupyter 模式,而且任何以 FROM 基礎映像檔建置出來的東西都會繼承它。

進入點做了哪些事

每個步驟都是冪等的,所以停止再啟動執行個體時,可以安全地在同一個容器上重跑一次。

步驟細節
1. 匯出環境容器環境會寫入 /etc/environment/etc/profile.d/superheat-env.sh,因為 sshd 與 Jupyter 產生的是不會繼承環境的登入 shell。佈建用的機密值會被排除在外。
2. 安裝金鑰PUBLIC_KEYSUPERHEAT_SSH_PUBLIC_KEYS 會寫入 /root/.ssh/authorized_keys
3. 啟動 sshd主機金鑰若不存在就會產生,接著 sshd 會在容器連接埠 22 上接聽。只接受金鑰;不接受密碼。
4. 啟動 Jupyter只有在設定了 JUPYTER_TOKEN 時才執行。系統會產生一次自我簽署憑證,並讓 JupyterLab 透過 HTTPS 繫結到 0.0.0.0:${JUPYTER_PORT}
5. 執行 onstartSUPERHEAT_ONSTART 只執行一次,由一個哨兵檔把關。失敗會被記錄下來,容器仍會保持運作。
6. 交棒若映像檔有 CMD 就會執行它;否則容器會閒置,以維持執行狀態讓連接埠對應保持有效。

環境契約

這些變數名稱是 Superheat 與映像檔之間的介面。以基礎映像檔為底建置,進入點會替你處理它們;自己寫進入點,這些就是你必須實作的東西。

變數用途
PUBLIC_KEY單一 OpenSSH 公開金鑰,附加到 authorized_keys
SUPERHEAT_SSH_PUBLIC_KEYS以換行分隔的 OpenSSH 公開金鑰,附加到 authorized_keys
SUPERHEAT_ONSTART在首次啟動時執行一次的 bash。屬敏感值;不會保存到環境檔案中。也接受 ONSTART 這個簡短別名
JUPYTER_TOKEN設定後,JupyterLab 會以它作為存取權杖啟動
JUPYTER_PORTJupyter 繫結的連接埠,預設為 8080
JUPYTER_DIRJupyter 的根目錄,預設為 /workspace
JUPYTER_LABtrue 使用 JupyterLab(預設),false 使用傳統 notebook
OPEN_BUTTON_PORT僅供參考 —— 主控台 開啟 按鈕的目標連接埠
CONTAINER_ID僅供參考 —— 工作負載識別碼
GPU_COUNT僅供參考 —— 指派了多少個 GPU
SUPERHEAT_TCP_PORT_<n>僅供參考 —— 容器連接埠 <n> 對外發布的主機連接埠

Superheat 會最後才設定這些值,排在你的範本環境變數與任何租用者覆寫之後,所以它們都不會被蓋掉。請參閱環境變數

建置你自己的映像檔

從 CUDA 版本符合你程式碼需求的標籤繼承,安裝你的相依套件,並且不要動進入點:

FROM superheat/base:cuda-12.4

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

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

三條規則能讓成果在 sshjupyter 模式下仍可啟動:

  1. 要繼承,不要重建。nvidia/cuda 開始建置並自行複製一份 sshd 進去,會失去 com.superheat.base 標籤,連帶失去進入點契約。
  2. 不要覆寫 ENTRYPOINT 基礎進入點負責啟動 sshd、Jupyter 與你的啟動時指令碼。覆寫它會讓 ssh 範本變成一個沒有任何方式能連進去的容器。
  3. 把你的程序放進 CMD 進入點會在佈建完成後執行 CMD,因此用這種方式啟動的長時間執行伺服器,旁邊還會有 sshd 與 Jupyter 一起跑。

如果你的映像檔沒辦法遵守這些規則 —— 例如不受你控制的上游映像檔,或本身就有進入點的映像檔 —— 請改用 args 啟動模式。它會執行任何映像檔原生的進入點,完全不需要基礎映像檔提供什麼。請參閱啟動模式

該從哪個標籤繼承

情況標籤
你的框架釘選了某個 CUDA 次版本對應的 cuda-<minor>
你想要最新可用的 CUDA,而且可以重新建置latest
你需要幾個月後仍解析成完全相同的建置sha-… 標籤

釘選 cuda-<minor> 標籤是常見的做法。每當新的 CUDA 次版本發布時,latest 就會跟著移動;這對開發用映像檔沒問題,但拿來當可重現訓練任務的基礎就很糟。

檔案系統配置

路徑內容
/workspace工作目錄,預設也是 Jupyter 的根目錄
/opt/superheat/entrypoint.sh佈建進入點
/var/lib/superheat/onstart.sh實際執行的啟動時指令碼內容
/var/lib/superheat/.onstart-done阻止啟動時指令碼重複執行的哨兵檔
/var/log/superheat/onstart.log啟動時指令碼的輸出
/var/log/superheat/jupyter.logJupyter 的輸出
/etc/profile.d/superheat-env.sh登入 shell 所看到的環境

sshd 與 Jupyter 也會把輸出串流到容器日誌,也就是主控台顯示的內容。請參閱日誌