> ## Documentation Index
> Fetch the complete documentation index at: https://docs.novita.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Build Template

A **template** is the blueprint a sandbox is created from — it defines the base image, installed packages, files, environment, and the commands that run at startup. Every sandbox is spawned from a template, so building a template is how you produce a reusable, ready-to-run environment.

Templates are conceptually close to container images: a template is **built from a Docker image**, and the build process is **similar to writing a Dockerfile** — you start from a base image and layer instructions on top. The difference is where and how you express those instructions.

| | Template | Dockerfile / Docker image |
| - | - | - |
| Starts from | A **Docker image** (e.g. `fromImage('python:3.12')`) or another template | A base image via `FROM` |
| How steps are written | SDK builder calls — `runCmd`, `copy`, `setEnvs`, … (like Dockerfile instructions, but in code) | Dockerfile instructions — `RUN`, `COPY`, `ENV`, … |
| Extra config | Also captures sandbox settings: start command, ready command, CPU / memory | Only the image contents |
| Result | A `templateId` you pass to `sandbox.create(...)` | An image you run as a container |

In short: a template **starts from a Docker image**. Building one feels similar to authoring a Dockerfile, but you describe the steps with the SDK (`fromImage`, `runCmd`, `copy`, `setEnvs`, …) instead of a `Dockerfile`. The output is a `templateId` that Novita uses to launch sandboxes quickly.

***

## Build

Once a template definition is ready, use `novita.template.build(...)` to build it.

```js JavaScript & TypeScript icon="js" theme={"system"}
import { Novita } from 'novita-sandbox'

const novita = new Novita()
const template = novita.template.new().fromImage('python:3.12')

const build = await novita.template.build(template, 'my-python-template', {
  cpuCount: 2,
  memoryMB: 1024,
})

const sandbox = await novita.sandbox.create(build.templateId)
console.log(sandbox.sandboxId)

await sandbox.kill()
```

```python Python icon="python" theme={"system"}
from novita_sandbox import Novita

novita = Novita()
template = novita.template.new().from_image("python:3.12")

build = novita.template.build(
    template,
    "my-python-template",
    cpu_count=2,
    memory_mb=1024,
)

sandbox = novita.sandbox.create(build.template_id)
print(sandbox.sandbox_id)

sandbox.kill()
```

```bash CLI icon="terminal" theme={"system"}
# Build a Dockerfile into a Sandbox template (alias: template ct)
# Reads ./novita.Dockerfile (or Dockerfile) in the root directory by default
novita template create my-python-template

# Specify a Dockerfile, resources, and start command
novita template create my-python-template \
  --dockerfile ./novita.Dockerfile \
  --cpu-count 2 \
  --memory-mb 1024 \
  --cmd "python app.py"
```

## Names

Every build needs a template name. Keep names stable for a logical template family. The returned template ID is the immutable build output you use at runtime.

## Base Image

A template definition always starts by choosing a base image (or an existing template) with one of the `from*` methods.

```js JavaScript & TypeScript icon="js" theme={"system"}
import { Novita } from 'novita-sandbox'

const novita = new Novita()

// Novita's default base image
const base = novita.template.new().fromBaseImage()

// A specific language image
const python = novita.template.new().fromPythonImage('3.12')
const ubuntu = novita.template.new().fromUbuntuImage('24.04')

// A custom image (optionally with private registry credentials)
const custom = novita.template
  .new()
  .fromImage('myregistry.com/myimage:latest', {
    username: 'user',
    password: 'pass',
  })
```

```python Python icon="python" theme={"system"}
from novita_sandbox import Novita

novita = Novita()

# Novita's default base image
base = novita.template.new().from_base_image()

# A specific language image
python = novita.template.new().from_python_image("3.12")
ubuntu = novita.template.new().from_ubuntu_image("24.04")

# A custom image (optionally with private registry credentials)
custom = novita.template.new().from_image(
    "myregistry.com/myimage:latest",
    credentials={"username": "user", "password": "pass"},
)
```

## User and Workdir

After choosing a base image, you can control which user subsequent build steps run as and which directory they run in.

```js JavaScript & TypeScript icon="js" theme={"system"}
import { Novita } from 'novita-sandbox'

const novita = new Novita()
const template = novita.template
  .new()
  .fromUbuntuImage('24.04')
  .setUser('root')
  .aptInstall(['git'])
  .setUser('user')
  .setWorkdir('/home/user/app')
```

```python Python icon="python" theme={"system"}
from novita_sandbox import Novita

novita = Novita()
template = (
    novita.template.new()
    .from_ubuntu_image("24.04")
    .set_user("root")
    .apt_install(["git"])
    .set_user("user")
    .set_workdir("/home/user/app")
)
```

## Tags & versioning

Tags let you label builds for release management without changing the underlying template name.

```js JavaScript & TypeScript icon="js" theme={"system"}
import { Novita } from 'novita-sandbox'

const novita = new Novita()
const template = novita.template.new().fromPythonImage('3.12')

const build = await novita.template.build(template, 'agent-runtime-base', {
  tags: ['v1.0.0', 'latest'],
})

await novita.template.assignTags('agent-runtime-base:v1.0.0', 'production')

const tags = await novita.template.getTags(build.templateId)
console.log(tags)
```

```python Python icon="python" theme={"system"}
from novita_sandbox import Novita

novita = Novita()
template = novita.template.new().from_python_image("3.12")

build = novita.template.build(
    template,
    "agent-runtime-base",
    tags=["v1.0.0", "latest"],
)

novita.template.assign_tags("agent-runtime-base:v1.0.0", "production")

tags = novita.template.get_tags(build.template_id)
print(tags)
```

## Logging

Build logs help you inspect provisioning progress and diagnose failures.

```js JavaScript & TypeScript icon="js" theme={"system"}
import { Novita } from 'novita-sandbox'

const novita = new Novita()
const template = novita.template.new().fromPythonImage('3.12')

const build = await novita.template.build(template, 'my-logged-template')
console.log(build.buildId)
```

```python Python icon="python" theme={"system"}
from novita_sandbox import Novita

novita = Novita()
template = novita.template.new().from_python_image("3.12")

build = novita.template.build(template, "my-logged-template")
print(build.build_id)
```

## Error handling

Template builds can fail for several common reasons:

* invalid credentials for a private registry
* package install failures inside `runCmd(...)` / `run_cmd(...)`
* a start command that exits unexpectedly
* a ready command that never succeeds
* CPU and memory settings that do not satisfy platform limits


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.