Tunnel
graft host tunnel forwards a remote container’s port to your local machine, letting you connect to any running service as if it were local.
graft host tunnel <container> [-port <remote>:<local>]
Section titled “graft host tunnel <container> [-port <remote>:<local>]”graft host tunnel backend -port 5000:8080 # container port 5000 → localhost:8080graft host tunnel frontend -port 3000 # container port 3000 → localhost:3000graft host tunnel graft-postgres # auto-detect the exposed portgraft -r azure tunnel backend -port 5000:8080 # via registryThe port mapping is passed with -port (or --port):
| Form | Remote port | Local port |
|---|---|---|
-port 5000:8080 | 5000 | 8080 |
-port 3000 | 3000 | 3000 |
| omitted | auto-detected | same as remote |
What it does:
- Connects to the remote server over SSH.
- Looks up the container’s IP on the Docker network.
- Auto-detects the container’s exposed port when
-portis omitted. If several ports are exposed, prompts you to pick one. - Forwards the remote port to your local port and holds the tunnel open until you press Ctrl+C.
Because the remote port is how Graft finds the service, there is no way to choose a local port without naming the remote one too. To reach a container’s port 5000 on local port 8080, write -port 5000:8080.
Use with any local tool — database GUIs, API clients, browsers, or your app’s dev config pointing at your local port.
The SSH connection behind the tunnel is self-healing: if it drops, Graft reconnects without tearing down your local listener, so you can open a tunnel once and leave it running.
graft db <name> serve
Section titled “graft db <name> serve”For Postgres databases created with graft db init, the db serve command is a shortcut that also prints credentials from .graft/secrets.env.
Note that db serve takes a bare :port for the local port — graft db myapp serve :5433 — which is a different syntax from the -port flag used by host tunnel.