DEV Community

Cover image for Templates, Kits, Ports, SSH Integrations & Daily Workflows
Koti Vellanki
Koti Vellanki

Posted on

Templates, Kits, Ports, SSH Integrations & Daily Workflows

Blog 4 — Docker Sandboxes Series

What We Are Building

By the end of this blog you will turn a one-off sandbox into a reusable, daily development environment.

You will:

  • Understand and use custom templates
  • Apply kits for extra tools, network rules and startup behaviour
  • Publish ports so you can open services from your browser
  • Connect VS Code or Cursor to the sandbox over SSH
  • Use the interactive TUI and practical day-to-day patterns

After this blog a sandbox should feel like a normal remote development machine — just safer.

Why This Matters

In Blog 3 we successfully ran agents and used Docker inside the sandbox. That is powerful, but repeating the same setup every time is tiring.

You want:

  • The same tools pre-installed for every team member
  • Easy access to the web app the agent just started
  • Your favourite editor (VS Code / Cursor) connected to the isolated environment
  • A clean way to start, stop and manage multiple sandboxes

Templates, kits, ports and SSH give you exactly that.

What You Should Know Before Starting

  • Blogs 1–3 completed
  • A working project (we will reuse agent-lab or create a fresh one)
  • VS Code or Cursor installed (optional but recommended for the SSH part)
  • Docker Desktop is required only if you want to build your own template image

Environment Setup

Clean previous test sandboxes:

sbx ls
sbx stop $(sbx ls -q) 2>/dev/null || true
sbx rm $(sbx ls -q) 2>/dev/null || true
Enter fullscreen mode Exit fullscreen mode
➜  agent-lab git:(main) ✗ sbx ls
No sandboxes found.
Launch one: sbx run claude
➜  agent-lab git:(main)
Enter fullscreen mode Exit fullscreen mode

Go back to the project (or recreate it quickly):

cd agent-lab || (mkdir -p agent-lab && cd agent-lab)
Enter fullscreen mode Exit fullscreen mode

I'm on agent-lab directory
Output

➜  agent-lab git:(main)pwd
/Users/koti/myFuture/writings/docker/sandboxes/agent-lab
➜  agent-lab git:(main)
Enter fullscreen mode Exit fullscreen mode

Step 1 — Custom Templates (Reusable Base Environments)

Official templates live under docker/sandbox-templates:<variant>.

Most agents already use the -docker variant by default (full Docker Engine inside the microVM).

You can point to any template:

sbx run --name templated --template docker.io/docker/sandbox-templates:shell-docker shell
Enter fullscreen mode Exit fullscreen mode

sbx run template

Building your own template (optional)

If you have Docker Desktop:

# Dockerfile
FROM docker/sandbox-templates:shell-docker

USER root
RUN apt-get update && apt-get install -y \
    tree \
    jq \
    httpie \
    && rm -rf /var/lib/apt/lists/*

USER agent
Enter fullscreen mode Exit fullscreen mode

Build and use it:

# build docker image
docker build -t my-dev-template:v1 .
Enter fullscreen mode Exit fullscreen mode

sbx template docker build

#run the container
sbx run --name custom-template --template my-dev-template:v1 shell
Enter fullscreen mode Exit fullscreen mode

sbx run

This error is expected

Docker Sandboxes cannot see images that exist only in your local Docker Desktop / Docker Engine.The sbx runtime has its own separate image store. When you run the following command it tries to pull the image from a registry → gets 403 Forbidden because the image only exists locally.

sbx run --name custom-template --template my-dev-template:v1 shell
Enter fullscreen mode Exit fullscreen mode

Correct way to use a locally built custom template

Follow these exact steps:

1. Save your local image as a tar file

docker image save my-dev-template:v1 -o my-dev-template.tar
Enter fullscreen mode Exit fullscreen mode

2. Load it into the Sandbox runtime

sbx template load my-dev-template.tar
Enter fullscreen mode Exit fullscreen mode

3. Now run the sandbox using the template

sbx run --name custom-template --template my-dev-template:v1 shell
Enter fullscreen mode Exit fullscreen mode

sbx run commands description


Useful commands after loading

# See templates available to sbx in host terminal
sbx template ls
Enter fullscreen mode Exit fullscreen mode

Output

➜  agent-lab git:(main) ✗ sbx template ls
REPOSITORY                           TAG                  IMAGE ID       FLAVOR               CREATED
docker.io/docker/sandbox-templates   claude-code-docker   ae8a46a10575   claude-code-docker   3 days ago
docker.io/docker/sandbox-templates   shell-docker         d86a6cdc105a   shell-docker         3 days ago
docker.io/library/my-dev-template    v1                   b403131ff1e6   shell-docker         2 minutes ago
➜  agent-lab git:(main)
Enter fullscreen mode Exit fullscreen mode
# Remove a template if needed
sbx template rm my-dev-template:v1
Enter fullscreen mode Exit fullscreen mode

Inside the new sandbox you already have tree, jq and httpie without installing them again.

Output

agent@custom-template:agent-lab$ tree
.
|-- Dockerfile
`-- my-dev-template.tar

1 directory, 2 files
agent@custom-template:agent-lab$ jq
jq - commandline JSON processor [version 1.8.1]

Usage:  jq [options] <jq filter> [file...]
    jq [options] --args <jq filter> [strings...]
    jq [options] --jsonargs <jq filter> [JSON_TEXTS...]

jq is a tool for processing JSON inputs, applying the given filter to
its JSON text inputs and producing the filter's results as JSON on
standard output.

The simplest filter is ., which copies jq's input to its output
unmodified except for formatting. For more advanced filters see
the jq(1) manpage ("man jq") and/or https://jqlang.org/.

Example:

    $ echo '{"foo": 0}' | jq .
    {
      "foo": 0
    }

For listing the command options, use jq --help.
agent@custom-template:agent-lab$ httpie
usage: httpie [-h] [--debug] [--traceback] [--version] {cli,plugins} ...
httpie: error: Please specify one of these: 'cli', 'plugins'

This command is only for managing HTTPie plugins.
To send a request, please use the http/https commands:

  $ http POST pie.dev/post hello=world

  $ https POST pie.dev/post hello=world

agent@custom-template:agent-lab$
Enter fullscreen mode Exit fullscreen mode

Template vs Kit Diagram

template vs kit

Explanation

A template is a Docker image — heavy things that rarely change (language runtimes, system packages, Docker itself).

A kit is applied at runtime — lighter, declarative additions (extra tools, network allow-list, startup scripts, files).

Step 2 — Kits (Declarative Extensions)

Kits are YAML files (spec.yaml). They can be local directories, Git URLs or OCI artifacts.

Simple example — create a small kit that adds a useful tool and allows a domain:

mkdir -p my-kit

cat > my-kit/spec.yaml << 'EOF'
schemaVersion: "1"
kind: mixin
name: handy-tools
description: Adds a few everyday tools and allows example.com

commands:
  startup:
    - command: ["bash", "-c", "sudo apt-get update && sudo apt-get install -y tree jq || true"]
      user: "root"

network:
  allowedDomains:
    - "example.com:443"
EOF
Enter fullscreen mode Exit fullscreen mode

Run with the kit:

sbx run --name with-kit --kit my-kit shell
Enter fullscreen mode Exit fullscreen mode

Inside the sandbox jq is available and example.com is reachable.

You can stack multiple kits with repeated --kit flags.

Step 3 — Publishing Ports

*This we have covered in previous blog but for the simplicity and to get familiarised I'm adding detailed section for ports here. *

Sandboxes are network-isolated by default. To open a service from your host browser you must publish a port.

Start a simple server inside a sandbox (or let the agent do it):

sbx run --name port-demo --clone shell
# inside the sandbox
python3 -m http.server 8000
Enter fullscreen mode Exit fullscreen mode

From the host:

sbx ports port-demo --publish 8000
# or pin a host port
sbx ports port-demo --publish 8080:8000
Enter fullscreen mode Exit fullscreen mode

Check:

sbx ports port-demo
sbx ls
Enter fullscreen mode Exit fullscreen mode

Output

➜  agent-lab git:(main) ✗ sbx ports port-demo --publish 8080:8000
Published 127.0.0.1:8080 -> 8000/tcp
Published [::1]:8080 -> 8000/tcp
➜  agent-lab git:(main) ✗ 
➜  agent-lab git:(main) ✗ 
➜  agent-lab git:(main) ✗ sbx ports port-demo
HOST IP     HOST PORT   SANDBOX PORT   PROTOCOL
127.0.0.1   8080        8000           tcp
::1         8080        8000           tcp
127.0.0.1   49156       9418           tcp
127.0.0.1   49157       8000           tcp
::1         49157       8000           tcp
➜  agent-lab git:(main) ✗ sbx ls
SANDBOX     AGENT   STATUS    PORTS                                                                                                                     WORKSPACE
port-demo   shell   running   127.0.0.1:8080->8000/tcp, ::1:8080->8000/tcp, 127.0.0.1:49157->8000/tcp, ::1:49157->8000/tcp, 127.0.0.1:49156->9418/tcp   /Users/koti/myFuture/writings/docker/sandboxes/agent-lab
with-kit    shell   stopped                                                                                                                             /Users/koti/myFuture/writings/docker/sandboxes
➜  agent-lab git:(main)
Enter fullscreen mode Exit fullscreen mode

Open http://localhost:8080 (or the ephemeral port shown).

sbx hello

Unpublish when finished:

sbx ports port-demo --unpublish 8080:8000
Enter fullscreen mode Exit fullscreen mode

Port Publishing Diagram

port publishing

Explanation

Traffic from your browser hits a port on the host. sbx ports forwards it into the microVM. The app never needs to bind to the host network directly.

Step 4 — SSH Integration (VS Code / Cursor)

One-time setup:

sbx setup ssh
Enter fullscreen mode Exit fullscreen mode

Output

➜  agent-lab git:(main) ✗ sbx setup ssh
SSH ──────────────────────────────────────────────────────
Status       ● enabled · signed in as vellankikoti
Access       *.sbx -> sandboxd.sock (no port · login-gated)

Connect ──────────────────────────────────────────────────────
Terminal     ssh <sandboxname>.sbx
File access  sftp <sandboxname>.sbx
Copy files   scp myfile.txt <sandboxname>.sbx:/path/to/workspace/

You can safely re-run sbx setup ssh to reconfigure
➜  agent-lab git:(main)
Enter fullscreen mode Exit fullscreen mode

This writes a managed block into your SSH config so any *.sbx host is handled by the sbx daemon.

Create or use a named sandbox:

sbx create --name editor-demo shell .
sbx run --name editor-demo
Enter fullscreen mode Exit fullscreen mode

Output

sbx create run

Connect:

ssh editor-demo.sbx
Enter fullscreen mode Exit fullscreen mode

Output

➜  agent-lab git:(main) ✗ sbx ls
SANDBOX       AGENT   STATUS    PORTS   WORKSPACE
editor-demo   shell   running           /Users/koti/myFuture/writings/docker/sandboxes/agent-lab
➜  agent-lab git:(main) ✗ 
➜  agent-lab git:(main) ✗ sbx run --name editor-demo


Starting shell agent in sandbox 'editor-demo'...
Workspace: /Users/koti/myFuture/writings/docker/sandboxes/agent-lab

agent@editor-demo:agent-lab$ ls
multi_line.txt
agent@editor-demo:agent-lab$
Enter fullscreen mode Exit fullscreen mode

Try SSH to sbx

➜  agent-lab git:(main) ✗ ssh editor-demo.sbx       

Connecting to sandbox "editor-demo"…
agent@editor-demo:workspace$ 
agent@editor-demo:workspace$ pwd
/home/agent/workspace
agent@editor-demo:workspace$ cd /Users/koti/myFuture/writings/docker/sandboxes/agent-lab
agent@editor-demo:agent-lab$ ls
multi_line.txt
agent@editor-demo:agent-lab$
Enter fullscreen mode Exit fullscreen mode

SSH Connection Diagram

ssh connection

Explanation

The editor talks to a local proxy provided by sbx. No inbound port is opened on the microVM. Authentication is tied to your Docker login. The sandbox starts automatically if it was stopped.

Step 5 — Daily Workflow Patterns & TUI

Launch the interactive dashboard:

sbx
Enter fullscreen mode Exit fullscreen mode

You get a live view of all sandboxes (CPU, memory, status). From here you can create, start/stop, attach, open a shell or remove sandboxes. There is also a network panel.

Practical patterns I use every day:

  • Named sandboxes per feature: --name feature-login
  • Always prefer --clone for agent work
  • Publish only the ports you need
  • Connect the editor once and leave it attached
  • Clean up with sbx rm when the task is done

Multiple workspaces example:

sbx run --name multi claude ~/main-project ~/shared-libs:ro ~/docs:ro
Enter fullscreen mode Exit fullscreen mode

Let’s Break It

  1. Publish a port, open the service, then unpublish and confirm the browser can no longer reach it.
  2. Connect VS Code, make a change, and confirm it appears both in the editor and on the host (or via the clone remote).
  3. Apply a kit that denies a domain and watch the agent fail to reach it.

Production Thinking

In a real team I would:

  • Publish a small set of internal templates to a private registry
  • Keep common kits in the project repository (./kits/)
  • Document the exact sbx run ... --kit ... command in the README
  • Prefer SSH + editor over pure terminal for longer sessions
  • Use the TUI for quick overview of resource usage

Security Considerations

  • Templates and kits can install packages with root inside the microVM — treat them like any other code you run
  • Port publishing intentionally punches a controlled hole from host → sandbox
  • SSH access is still subject to the same network policy and workspace rules
  • Kits can declare their own network allow-lists; those rules are enforced

Common Mistakes

  • Forgetting sbx setup ssh before trying to connect an editor
  • Publishing ports on a stopped sandbox
  • Building templates without Docker Desktop
  • Putting secrets inside a template image instead of using sbx secret
  • Leaving many sandboxes with large Docker image caches

Troubleshooting

Problem Check Fix
*.sbx not resolving sbx setup ssh Re-run the setup command
Port not reachable sbx ports <name> Publish again or check the mapping
Editor cannot find folder Absolute path inside sandbox Use the host path that was mounted
Kit not applying sbx ls / logs Check kit path and spec.yaml syntax
Template pull fails Image name Use full docker.io/... reference

Useful commands:

sbx ports <name>
sbx setup ssh
ssh <name>.sbx
sbx
sbx exec -it <name> bash
Enter fullscreen mode Exit fullscreen mode

Cleanup

sbx stop port-demo editor-demo with-kit custom-template 2>/dev/null || true
sbx rm port-demo editor-demo with-kit custom-template 2>/dev/null || true
Enter fullscreen mode Exit fullscreen mode

What We Learned

  • Templates give you reusable base images with tools pre-installed
  • Kits add lightweight, declarative capabilities at runtime
  • sbx ports makes services inside the sandbox reachable from the host
  • SSH turns the sandbox into a first-class remote development target for VS Code and Cursor
  • The combination makes daily agent work feel natural and safe

You now have everything needed for comfortable, repeatable development inside sandboxes.

What’s Next?

In the final blog (Blog 5) we go deep into the security model, realistic troubleshooting, known limitations, organisation governance concepts, and production best practices so you can introduce Docker Sandboxes to a real team with confidence.

References

All commands and behaviour verified against current official documentation (August 2026).

Top comments (0)