How to Create Templates from OCI Images in CubeSandbox

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 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 (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 (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 (lines 74–97), which calls skopeo to download the OCI layout into a temporary directory. Following the pull, 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 (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 (lines 98–115).

Distribution occurs via 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 (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:

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:

cubemastercli template watch --job-id $JOB_ID

Programmatic Integration

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

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:

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 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, and 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. It then uses umoci to unpack the OCI layout into a mutable filesystem bundle, as implemented in 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, 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →