# How to Create Templates from OCI Images in CubeSandbox

> Learn how to create templates from OCI images in CubeSandbox. Discover the ten-stage pipeline that converts container images into reusable templates.

- Repository: [Tencent Cloud/CubeSandbox](https://github.com/TencentCloud/CubeSandbox)
- Tags: how-to-guide
- Published: 2026-07-11

---

**CubeSandbox converts OCI container images into immutable, reusable templates by orchestrating a ten-stage pipeline that pulls images with skopeo, unpacks them using umoci, builds ext4 rootfs images, and distributes artifacts across cluster nodes.**

CubeSandbox, TencentCloud's open-source sandbox runtime, enables instant container startup by transforming standard OCI images into pre-configured templates. Understanding the process for **creating templates from OCI images in CubeSandbox** is essential for operators who want to optimize sandbox provisioning and eliminate cold-start latency. The workflow spans the `cubemastercli` command-line tool and the Cube Master service, with core logic implemented in [`CubeMaster/cmd/cubemastercli/commands/cubebox/template.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/CubeMaster/cmd/cubemastercli/commands/cubebox/template.go) and the `CubeMaster/pkg/templatecenter` package.

## The Template Creation Pipeline

Creating a template from an OCI image reference (e.g., `docker.io/library/nginx:latest`) follows a structured pipeline that converts container layers into a bootable ext4 rootfs. The process begins with a CLI request and concludes with a distributed template ready for sandbox instantiation.

### CLI Request Construction

The workflow initiates when `cubemastercli template create-from-image` parses flags including the image reference, writable-layer size, network configuration, and container overrides. In [`CubeMaster/cmd/cubemastercli/commands/cubebox/template.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/CubeMaster/cmd/cubemastercli/commands/cubebox/template.go) (lines 751–815), the `TemplateCreateFromImageCommand` constructs a `CreateTemplateFromImageReq` message and marshals it to JSON. The CLI then POSTs this payload to the Cube Master endpoint `POST /cube/template/from-image` (lines 828–831), triggering an asynchronous job.

### Server-Side Job Orchestration

Upon receiving the request, Cube Master creates a **Template-Image Job** in [`CubeMaster/pkg/templatecenter/template_image.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/CubeMaster/pkg/templatecenter/template_image.go) (lines 140–165). This persistent record receives a generated `job_id` and `template_id`, which are immediately returned to the CLI while background processing begins. The job tracks phases including **PULLING**, **UNPACKING**, **BUILDING_EXT4**, **DISTRIBUTING**, and **CREATING_TEMPLATE**, with progress updates stored in the job record.

### Image Acquisition and Unpacking

The job runner invokes `StreamRegistryToDir` in [`CubeMaster/pkg/templatecenter/image/native.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/CubeMaster/pkg/templatecenter/image/native.go) (lines 74–97), which calls **skopeo** to download the OCI layout into a temporary directory. Following the pull, [`CubeMaster/pkg/templatecenter/image/export.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/CubeMaster/pkg/templatecenter/image/export.go) (lines 48–100) executes `umoci unpack --rootless` to convert the OCI layout into a mutable bundle—a filesystem tree that can be modified before rootfs creation.

### Rootfs Construction and Distribution

In [`CubeMaster/pkg/templatecenter/image/engine.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/CubeMaster/pkg/templatecenter/image/engine.go) (lines 210–260), the **ext4 builder** creates an ext4 image from the unpacked bundle. This stage optionally injects the CubeEgress root CA when the `--with-cube-ca` flag is enabled. The resulting ext4 file is hashed with SHA-256 and stored as an artifact in [`CubeMaster/pkg/templatecenter/image/image.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/CubeMaster/pkg/templatecenter/image/image.go) (lines 98–115).

Distribution occurs via [`CubeMaster/pkg/templatecenter/snapshot_ops.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/CubeMaster/pkg/templatecenter/snapshot_ops.go) (lines 30–78), where the artifact is copied to every node matching the job's `distribution_scope`. Each target node creates a **snapshot** that the template references for sandbox creation.

### Template Registration

Once distribution completes successfully, the job updates its status to `READY` in [`CubeMaster/pkg/templatecenter/template_image.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/CubeMaster/pkg/templatecenter/template_image.go) (lines 332–358). The final template record stores the template ID, image information, network configuration, CA bake flag, and snapshot references. At this point, the template is ready for use in sandbox creation commands (`template commit`, `template create`, etc.).

## Practical Implementation

The following examples demonstrate how to interact with the template creation pipeline via the CLI and Go SDK.

### Creating Templates via CLI

To build an ext4 rootfs from the nginx image and create a template asynchronously:

```bash
cubemastercli template create-from-image \
  --image docker.io/library/nginx:latest \
  --writable-layer-size 20Gi \
  --instance-type cubebox \
  --network-type tap \
  --allow-internet-access \
  --expose-port 80 \
  --cpu 2000 \
  --memory 2000 \
  --with-cube-ca

```

The command returns a JSON payload containing `job_id` and `template_id`. Monitor the job progress with:

```bash
cubemastercli template watch --job-id $JOB_ID

```

### Programmatic Integration

You can construct the same request programmatically using the `types` package from the CubeSandbox repository:

```go
import (
    "bytes"
    "net/http"
    "github.com/tencentcloud/CubeSandbox/CubeMaster/pkg/service/sandbox/types"
    "github.com/google/uuid"
    jsoniter "github.com/json-iterator/go"
)

req := &types.CreateTemplateFromImageReq{
    Request:           &types.Request{RequestID: uuid.New().String()},
    SourceImageRef:    "docker.io/library/nginx:latest",
    WritableLayerSize: "20Gi",
    InstanceType:      "cubebox",
    NetworkType:       "tap",
    ExposedPorts:      []int32{80},
    Cpu:               2000,
    Memory:            2000,
    WithCubeCA:        BoolPtr(true),
    ContainerOverrides: &types.ContainerOverrides{
        Envs: []*types.KeyValue{
            {Key: "ENV", Value: "production"},
        },
    },
}

body, _ := jsoniter.Marshal(req)
resp, _ := http.Post(
    "http://master-host:port/cube/template/from-image",
    "application/json",
    bytes.NewReader(body),
)

```

### Monitoring Job Status

To poll the job status programmatically until completion:

```go
func waitForJob(jobID string) (*types.TemplateImageJobInfo, error) {
    client := http.Client{Timeout: 10 * time.Second}
    for {
        url := fmt.Sprintf("http://master-host:port/cube/template/from-image?job_id=%s", jobID)
        resp, err := client.Get(url)
        if err != nil {
            return nil, err
        }
        var r templateImageJobResponse
        json.NewDecoder(resp.Body).Decode(&r)
        
        if r.Ret.RetCode != 200 {
            return nil, fmt.Errorf("API error: %s", r.Ret.RetMsg)
        }
        if r.Job.Status == "READY" || r.Job.Status == "FAILED" {
            return r.Job, nil
        }
        fmt.Printf("Progress: %d%% - Phase: %s\n", r.Job.Progress, r.Job.Phase)
        time.Sleep(2 * time.Second)
    }
}

```

## Summary

- **CubeSandbox** creates templates from **OCI images** through a pipeline involving CLI request construction, server-side job orchestration, image unpacking with **skopeo** and **umoci**, ext4 rootfs building, and node distribution.
- The core implementation resides in [`CubeMaster/cmd/cubemastercli/commands/cubebox/template.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/CubeMaster/cmd/cubemastercli/commands/cubebox/template.go) for the CLI interface and `CubeMaster/pkg/templatecenter` for the backend processing.
- Key functions include `StreamRegistryToDir` for image pulling, the ext4 builder in [`engine.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/engine.go), and [`snapshot_ops.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/snapshot_ops.go) for artifact distribution.
- Templates are immutable and include the ext4 rootfs, OCI spec fingerprint, and optional CubeEgress CA information, enabling instant sandbox startup without repeated image pulls.

## Frequently Asked Questions

### What tools does CubeSandbox use to pull OCI images?

CubeSandbox uses **skopeo** to stream OCI images from registries to local storage via the `StreamRegistryToDir` function in [`CubeMaster/pkg/templatecenter/image/native.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/CubeMaster/pkg/templatecenter/image/native.go). It then uses **umoci** to unpack the OCI layout into a mutable filesystem bundle, as implemented in [`CubeMaster/pkg/templatecenter/image/export.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/CubeMaster/pkg/templatecenter/image/export.go).

### How does the ext4 rootfs improve sandbox startup time?

The ext4 rootfs is a pre-built, immutable disk image that contains the complete container filesystem. Because the template stores this as a node-local snapshot, sandboxes can mount the rootfs instantly without requiring image pulls, layer extraction, or copy-on-write operations at startup time.

### Can I customize container settings during template creation?

Yes. The `CreateTemplateFromImageReq` struct accepts a `ContainerOverrides` field that allows you to specify environment variables, entrypoints, and other container configurations. These overrides are applied during the unpacking phase before the ext4 image is built, ensuring the template reflects your custom settings.

### What is the purpose of the distribution scope?

The `distribution_scope` parameter determines which cluster nodes receive the template artifact. According to [`CubeMaster/pkg/templatecenter/snapshot_ops.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/CubeMaster/pkg/templatecenter/snapshot_ops.go), the system copies the generated ext4 rootfs only to nodes matching this scope, ensuring that sandboxes can start on any compatible node without requiring network access to the original OCI registry.