跳至主要內容

連接埠與開啟按鈕

連接埠如何被發布​

容器內的連接埠在主機把它發布出去之前,是無法從網際網路連上的。啟動時,每個宣告的容器連接埠都會被對應到主機上的一個空閒連接埠,取自該主機可用的範圍。你連的是主機連接埠,而它幾乎不會和容器連接埠是同一個號碼 — 原因和你的 SSH 連接埠不是 22 一樣。

容器會透過每個已發布 TCP 連接埠各一個的環境變數,得知它的每個連接埠落在哪個主機連接埠上:

# inside the instance
env | grep SUPERHEAT_TCP_PORT_
# SUPERHEAT_TCP_PORT_22=40123
# SUPERHEAT_TCP_PORT_8080=41007

SUPERHEAT_TCP_PORT_<n> 存放容器連接埠 <n> 所對應的已發布主機連接埠。這只是資訊性的:它存在是為了讓執行個體上的處理程序能正確宣告自己的公開位址。UDP 連接埠沒有這種變數。

各種啟動模式會發布什麼​

連接埠來自範本,再加上啟動模式所需要的:

啟動模式自動發布然後
ssh容器連接埠 22加上範本上宣告的每一個連接埠
jupyter容器連接埠 22 與 8080加上範本上宣告的每一個連接埠
args不自動發布任何東西只有範本上宣告的連接埠
vm容器連接埠 22加上範本上宣告的每一個連接埠

宣告的連接埠可以帶一個標籤。標籤為 open、open_button 或 open-button 會把該連接埠標記為開啟按鈕的目標。其他所有標籤都只是描述性的,該連接埠會被當成一般的應用程式連接埠處理。

開啟按鈕​

當範本宣告了一個開啟按鈕連接埠時,執行個體的 連線 頁籤會在 SSH 指令上方顯示一個 開啟 按鈕,指向主機上的那個連接埠。它是你的映像檔所提供的網頁介面的捷徑 — 推論前端、儀表板、檢視器 — 讓你不必自己去查已發布的連接埠。

如果主機位於 NAT 之後、外部無法直接連上,開啟 按鈕指向的會是 https://<工作負載 ID>-<容器連接埠>.relay.superheat.cloud/ 形式的中繼網址,而不是主機上的連接埠;中繼只在 Superheat CN 啟用 superheat.cloud 網域之後才會開啟(請見開啟 JupyterLab)。

連接埠號碼也會以 OPEN_BUTTON_PORT 交給容器,以防處理程序需要知道主控台正在宣傳它的哪一個連接埠。

每一種啟動模式都可以有開啟按鈕,args 也不例外。args 模式的範本執行的是映像檔自己的 entrypoint,但它仍然會收到 OPEN_BUTTON_PORT,也仍然會有開啟按鈕 —— 否則提供網頁介面的映像檔就永遠無法從主控台開啟,而那正是 args 模式最主要的用途。

jupyter 模式的執行個體除了這個按鈕之外,還會有自己的 開啟 JupyterLab 按鈕。請見開啟 JupyterLab。

執行個體存取權杖​

範本需要時,每個執行個體在部署時都會拿到一個自己的密鑰:存取權杖。它和 JupyterLab 的權杖是同一個值。執行個體的 連線 分頁會在 存取權杖 底下顯示它,預設遮蔽,旁邊有 顯示存取權杖 與 複製存取權杖 按鈕;API 也會以執行個體的 access_token 把它回傳給你的組織。執行個體銷毀後它就失效了。

在 Superheat CN 上可以啟動的精選範本中,凡是在已發布的連接埠上提供網頁介面或 API 的,都會在那個連接埠上要求出示權杖:

範本連接埠怎樣出示權杖
ComfyUI、Stable Diffusion WebUI (A1111)、Fooocus、Kohya_ss、Faster-Whisper(它的語音辨識 API)應用程式的連接埠應用程式前面有一個存取代理。開啟 按鈕會替你登入;腳本傳送 Authorization: Bearer <權杖>
Text Embeddings Inference80服務把它當作自己的 API 金鑰來檢查:每個請求都要帶 Authorization: Bearer <權杖>
Open WebUI8080以 admin@superheat.local 登入,密碼就是權杖。註冊已關閉,別人無法再建立帳號

權杖只涵蓋範本開始要求它之後部署的執行個體。更早部署的執行個體,連接埠維持原樣——任何找到它們的人都連得上——直到你銷毀它為止;重新部署才會拿到權杖。

Triton Inference Server 同樣要求權杖,但它的映像檔來自 NVIDIA NGC,在 Superheat CN 上顯示為即將推出,請參閱Superheat CN 上的映像檔。Ollama、InvokeAI、LLaMA-Factory 與 vLLM 目前被標記為 即將推出:它們的服務無法在每條路由上都要求權杖 —— vLLM 的 API 金鑰會留下一條推論路由沒有防護 —— 所以在做到之前先下架。已經在執行的執行個體不受影響。

# 要求權杖的 API 連接埠 —— 這裡是 Text Embeddings Inference
curl -H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"inputs": "你好"}' \
http://203.0.113.14:41007/embed

開啟按鈕怎樣替你登入​

對於存取代理後面的範本,開啟 連結會以 ?token= 帶上權杖。第一次開啟時,代理會把權杖換成這個瀏覽器裡的一個 cookie,再把你導向不帶權杖的同一個網址,所以權杖會立刻離開網址列。之後在同一個瀏覽器裡造訪就不再需要權杖。既沒帶權杖、也沒帶這個 cookie 的請求會得到 401。

這個 cookie 只對應用程式自己的頁面,以及直接開啟應用程式時有效。由其他來源的頁面讓你的瀏覽器送出的請求 —— 包括同一台機器上的其他連接埠 —— 會被拒絕並回傳 403,所以主機上其他租用者的應用程式沒辦法借用你的 cookie 操作你的應用程式。

直接連線 —— 機器的 IP 位址加上一個已發布的連接埠 —— 走的是明文 HTTP。開啟 連結裡的權杖、這個 cookie,以及這條連線上的其他一切都是未加密傳輸,所以請像對待密碼一樣對待 開啟 連結:不要把它貼到你不會貼權杖的地方。

瀏覽器會把 cookie 送給同一個位址上的每一個連接埠,而不只是設定它的那一個。直接連線時,開啟同一台機器上其他租用者執行的應用程式——也就是這台機器位址上其他連接埠的任何連結——就等於把你的 cookie 交給對方,連同你的應用程式一起,只要執行個體還在就一直有效。請在另一個瀏覽器或無痕視窗裡開啟這個位址上別人的連結,或改用 SSH 轉送連上你自己的應用程式。

透過 SSH 轉送連接埠時不會經過代理,因為 SSH 已經驗證過你了。在代理後面,應用程式接聽的是 127.0.0.1,所以請轉送到這個位址:

ssh -N -L 8188:127.0.0.1:8188 -p 40123 root@203.0.113.14

你自己的範本​

你自己的範本,只有在連接埠宣告了要求方式時才會要求權杖 —— 也就是範本編輯器中這個連接埠的存取控制設定(存取代理或應用程式驗證權杖),或透過 API 設定的 auth。沒有這個欄位的連接埠照舊發布:任何找到機器位址和連接埠的人都連得上。請在它前面放一個會驗證的東西,或改用 SSH 轉送來存取。請參閱連接埠。

連上你自己啟動的服務​

連接埠是在執行個體啟動時發布的。在執行中的執行個體裡啟動伺服器不會發布任何東西,所以剛跑起來的 python -m http.server 8000 從外面連不上,不管你筆電上的防火牆怎麼設定都一樣。

你有兩個選擇。

在範本上宣告連接埠,然後重新部署。 對於任何你會執行不只一次的東西,這是持久的答案。把連接埠加到範本的連接埠清單底下,給它一個標籤,然後重新部署。請見連接埠。

透過 SSH 轉送。 這不需要重新部署,而且對於你沒有事先規劃的連接埠可以立即生效:

ssh -N -L 8000:localhost:8000 -p 40123 root@203.0.113.14

讓它一直跑著,然後在瀏覽器打開 http://localhost:8000。流量走的是你已經建立的 SSH 連線,所以不會有新的東西暴露到網際網路上。

不論你走哪條路,如果希望已發布的連接埠能用,請把你的服務綁定到 0.0.0.0 而不是 127.0.0.1。只接聽 loopback 的處理程序可以透過 SSH 轉送連上,但無法透過已發布的主機連接埠連上。唯一的例外是存取代理後面的應用程式:那裡的應用程式接聽 loopback,由代理佔住已發布的連接埠。

協定​

宣告的連接埠會指定一種協定:tcp、udp、http 或 https。前兩者才是實際在主機上保留的。後兩者只是關於該連接埠提供什麼服務的提示,而且都是走 TCP。

相關內容​