Skip to main content

Ports and the Open button

How a port gets published

A port inside your container is not reachable from the internet until the host publishes it. At launch, each declared container port is mapped to a free port on the host machine, taken from the range that host has available. The host port is what you connect to, and it is almost never the same number as the container port — the same reason your SSH port is not 22.

The container is told which host port each of its ports landed on, through one environment variable per published TCP port:

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

SUPERHEAT_TCP_PORT_<n> holds the published host port for container port <n>. This is informational: it is there so a process on the instance can advertise its own public address correctly. UDP ports get no such variable.

What each launch mode publishes

Ports come from the template, plus whatever the launch mode requires:

Launch modePublished automaticallyThen
sshcontainer port 22plus every port declared on the template
jupytercontainer ports 22 and 8080plus every port declared on the template
argsnothing automaticonly the ports declared on the template
vmcontainer port 22plus every port declared on the template

A declared port may carry a label. A label of open, open_button or open-button marks that port as the Open button target. Every other label is descriptive only, and the port is treated as a plain application port.

The Open button

When a template declares an open-button port, the instance's Connect tab shows an Open button above the SSH command, pointing at that port on the host. It is a shortcut for a web UI your image serves — an inference front end, a dashboard, a viewer — so you do not have to look the published port up.

The port number is also handed to the container as OPEN_BUTTON_PORT, in case the process needs to know which of its ports the console is advertising.

Every launch mode can have one, args included. An args-mode template runs the image's own entrypoint, but it still receives OPEN_BUTTON_PORT and still gets an Open button — without that, an image serving a web UI could never be opened from the console, which is most of what args mode is used for.

A jupyter-mode instance gets its own Open JupyterLab button in addition to this one. See Open JupyterLab.

Reaching a service you started yourself

Ports are published when the instance launches. Starting a server inside a running instance does not publish anything, so a fresh python -m http.server 8000 is not reachable from outside no matter what the firewall on your laptop does.

You have two options.

Declare the port on a template and deploy again. This is the durable answer for anything you will run more than once. Add the port under the template's ports, give it a label, and redeploy. See Ports.

Forward it over SSH. This needs no redeploy and works immediately for a port you did not plan for:

ssh -N -L 8000:localhost:8000 -p 40123 root@sh-us-tx-01.ssh.superheat.dev

Leave that running and open http://localhost:8000 in your browser. The traffic goes through the SSH connection you already have, so nothing new is exposed to the internet.

Whichever route you take, bind your service to 0.0.0.0 rather than 127.0.0.1 if you want the published port to work. A process listening only on loopback is reachable through SSH forwarding but not through a published host port.

Protocols

A declared port names a protocol: tcp, udp, http or https. The first two are what is actually reserved on the host. The last two are a hint about what the port serves, and they ride on TCP.