Puertos
Declare un puerto en una plantilla y Superheat lo publica cuando la instancia se lanza, asignando el puerto del contenedor a un puerto del host en la máquina que alquiló. Todo aquello en lo que escuche su carga de trabajo y quiera alcanzar desde fuera — un servidor de inferencia, una interfaz web, un endpoint de métricas — necesita una fila aquí.
Declarar un puerto
Cada fila de la sección Puertos tiene cinco partes.
| Parte | Acepta | Significado |
|---|---|---|
| Puerto del contenedor | de 1 a 65535 | El puerto en el que escucha su proceso dentro del contenedor. |
| Protocolo | tcp, udp, http, https | Lo que sirve el puerto. http y https se publican sobre TCP; la distinción deja constancia de la intención y determina cómo presenta el puerto la consola. |
| Etiqueta | hasta 64 caracteres | Un nombre legible, que se muestra en el detalle de la plantilla. Algunos valores están reservados — vea más abajo. |
| Público | interruptor, activado de forma predeterminada | Se registra en la entrada del puerto. |
| Acceso | Abierto, Proxy de acceso o La app verifica el token (el auth de la API: sin definir, proxy o app) | Si el puerto exige el token de acceso de la instancia, y quién lo comprueba. Consulte Exigir el token de acceso. |
Usted declara solo el puerto del contenedor. El puerto del host se asigna en el lanzamiento desde el rango publicado de la máquina, y no lo sabrá de antemano. Dentro del contenedor, cada puerto TCP publicado está disponible como SUPERHEAT_TCP_PORT_<container_port>:
echo "$SUPERHEAT_TCP_PORT_7860"
Esa variable de entorno es la forma de leer el puerto del host desde dentro de su carga de trabajo. La pestaña Conectar de la página de la instancia muestra el comando SSH y, cuando la plantilla lo tiene, el enlace Abrir o Abrir JupyterLab. Consulte Puertos y el botón Abrir.
Etiquetas
Las etiquetas se recortan y se comparan sin distinguir mayúsculas de minúsculas, y seis de ellas se asignan a los cuatro roles reservados.
| Etiqueta | Efecto |
|---|---|
open, open_button, open-button | Convierte este puerto en el destino del botón Abrir. El puerto se publica con el rol open_button y su número se pasa al contenedor como OPEN_BUTTON_PORT. |
ssh | Se publica con el rol ssh. |
jupyter | Se publica con el rol jupyter. |
app | Se publica con el rol app — el predeterminado. |
| cualquier otra cosa | Se conserva como etiqueta de visualización; el puerto se publica con el rol app. |
Así que un puerto etiquetado Jupyter, jupyter o JUPYTER significa lo mismo en los tres casos, mientras que Gradio UI es un puerto de aplicación normal con un nombre amistoso.
Puertos que usted no declara
Los modos de lanzamiento anteponen los puertos que necesitan. En modo ssh, el puerto de contenedor 22 se agrega por usted. En modo jupyter se agregan tanto el 22 como el 8080. Declararlos usted mismo es inofensivo pero redundante: la lista se deduplica por puerto de contenedor y protocolo, y la entrada implícita gana sobre una entrada app normal.
La precedencia, de mayor a menor, es ssh y jupyter, después open_button y después app. Eso es lo que permite que una plantilla declare un puerto en la lista y además apunte el botón Abrir a él: la entrada que sobrevive lleva el rol open_button.
En modo args no se antepone nada. Si quiere acceso SSH a una plantilla args, es usted quien debe ejecutar un servidor SSH en la imagen y declarar el puerto, o bien debería pasar al modo ssh con una imagen derivada de la base.
El puerto del botón Abrir
La consola muestra un botón Abrir en una instancia cuando la plantilla nombró un puerto destino. Defínalo etiquetando exactamente un puerto como open:
{
"ports": [
{ "container_port": 7860, "protocol": "http", "label": "open", "public": true },
{ "container_port": 9090, "protocol": "http", "label": "metrics", "public": true }
]
}
Etiquete más de un puerto como open y gana el último de la lista, que rara vez es lo que quería decir. Declare uno solo.
En modo jupyter no necesita ningún puerto de botón Abrir: la consola muestra Abrir JupyterLab a partir del rol de Jupyter, con el token de acceso ya en la URL. Consulte Abrir JupyterLab. Un puerto de botón Abrir detrás del proxy de acceso también recibe el token en su URL.
Exigir el token de acceso
Un puerto publicado es accesible para cualquiera que encuentre la dirección de la máquina y el puerto. Cada instancia puede llevar un secreto propio, el token de acceso, y el campo auth de un puerto indica cómo lo exige ese puerto:
Acceso (auth) | Quién comprueba el token | Qué tiene que hacer la plantilla |
|---|---|---|
Proxy de acceso (proxy) | El proxy de acceso de la imagen base de Superheat. Toma el puerto publicado y solo deja pasar a la aplicación las solicitudes que llevan el token —?token= del botón Abrir, la cookie por la que lo cambia, o Authorization: Bearer— | Use una imagen derivada de la base, e inicie la aplicación en "${SUPERHEAT_APP_HOST:-0.0.0.0}", por ejemplo --listen "${SUPERHEAT_APP_HOST:-0.0.0.0}". La imagen base define esa variable como 127.0.0.1 siempre que ejecuta el proxy. Una aplicación que aun así se enlace a 0.0.0.0 en un puerto protegido no llega a arrancar, en lugar de servir sin autenticación |
La app verifica el token (app) | La propia aplicación | Conecte el token a la autenticación propia de la aplicación: una entrada de entorno cuyo valor sea exactamente ${SUPERHEAT_ACCESS_TOKEN} se sustituye por el token al desplegar, y $SUPERHEAT_ACCESS_TOKEN está definida en el contenedor para args_str y onstart. La comprobación de la aplicación tiene que cubrir todas las rutas |
| Abierto (sin definir) | Nadie | Nada. El puerto se publica como siempre, y no se genera ningún token salvo que la plantilla esté en modo jupyter |
Se configura por puerto con el menú de acceso de la sección Puertos del editor de plantillas, o como auth a través de la API (POST /v1/templates o PATCH /v1/templates/{id}). Una plantilla guardada conserva el valor en ambos casos. En un puerto con proxy, el enlace Abrir lleva ?token=; en un puerto app no, porque es la aplicación la que le inicia sesión.
El editor avisa debajo de la lista de puertos cuando una elección no hará lo que dice. Los avisos no le impiden guardar:
| El aviso trata de | Cuándo | Por qué importa |
|---|---|---|
| Proxy de acceso en otra imagen | El puerto usa el proxy de acceso, pero la imagen no es una imagen de Superheat (superheat/<nombre>, con o sin un registro delante) | El proxy vive en la imagen base de Superheat. En cualquier otra imagen nada protege el puerto |
| La app verifica el token, pero el token nunca llega a la app | El puerto dice que la app comprueba el token, pero ninguna entrada de entorno tiene exactamente el valor ${SUPERHEAT_ACCESS_TOKEN}, y ni los argumentos ni el script de inicio usan $SUPERHEAT_ACCESS_TOKEN | La app no tiene ningún token que comprobar, así que no puede exigirlo |
| Un puerto web público que se deja Abierto | Un puerto público http o https no tiene regla de acceso | Cualquiera que encuentre la dirección y el puerto de la máquina puede usar la app que sirve |
Los valores de la plataforma prevalecen: una sustitución de entorno del arrendatario no puede reemplazar el token en una variable que lo lleva.
Los puertos forman parte de la receta
La lista de puertos es un campo de lanzamiento, así que editarla vuelve a generar el hash_id de la plantilla e invalida los enlaces compartidos fijados. Las instancias en ejecución conservan el mapa de puertos con el que se lanzaron; un puerto nuevo solo aparece en las instancias desplegadas después de la edición.