MODULE 4  ·  DAY 1

Packaging Models as OCI Artifacts

Ship a model like a container image — versioned, layered, registry-native

Kitfile weights adapter config prompts one sealed ModelKit — pushable to any OCI registry

Gourav Shah  ·  School of DevOps & AI  ·  KitOps · ModelKit · ORAS

M4·01

What you'll learn

Why models belong in OCI registries — and how to pack, push, and pull them.

12 34 Why an OCI artifact is the right home for a model — versioned & layered Author a Kitfile and pack a ModelKit with the kit CLI Push & pull across GHCR, Docker Hub, Quay, Harbor — one syntax Selective-pull just the weights; contrast KitOps with docker model

By the end you'll treat a model the way you treat an image: tagged, stored, and shipped.

M4·02

The problem with loose model files

Weights here, prompt there, config in Slack — every receiver re-assembles by hand.

shared drive: weights Slack link: prompts README: "also grab v3" Receiver re-assembles by hand versions drift wrong prompt + wrong weights nothing signed

Logistics teams solved this decades ago with a shipping manifest and a sealed, labelled crate.

M4·03

A ModelKit is a sealed, labelled crate

One signed bundle — open it and the contents are exactly what the manifest says.

Kitfile (manifest) model weights .gguf code LoRA adapter (M3B) config quantization prompts system prompt

Model weights + adapter + config + prompts, versioned together — the manifest names every item.

M4·04

An OCI artifact is a layered blob store

The same mechanism that stores container images stores anything — including model checkpoints.

Container image base OS layer app layer config layer same spec ModelKit model weights layer code / prompts layer manifest + config SHA-256 + signed

A layer is just bytes + a digest. Registries dedupe: retrain the prompt, only the config layer is pushed.

M4·05

KitOps, ModelKit & ORAS

A CNCF stack: the format, the CLI, and the library that speaks to every registry.

kit CLI pack · push · unpack · ModelKit format ORAS OCI Registry As Storage — push/pull typed artifacts OCI distribution API the standard every registry speaks GHCR · Docker Hub · Quay · Harbor · Artifactory · registry:2

Because it's plain OCI underneath, the same commands work on every compliant registry.

M4·06

The Kitfile — your shipping manifest

A tiny YAML file; each field maps to one typed OCI layer.

Kitfile manifestVersion: "1.0.0" package: {name, version, authors} model: {path: ./model/*.gguf} code: [{path: ./prompts.txt}] manifest annotation registry UI metadata model layer the weights blob code layer prompts / config

kit pack reads the Kitfile, hashes each file into a layer, and stores it in the local kit cache.

M4·07

The lifecycle: pack → push → pull → run

From a workspace to a serving node — the registry is the hub in the middle.

workspace kit pack Registry acme-docs-model:1.0.0 serving node kit unpack runtime llama.cpp push pull weights are never "run" as a container — unpacked to a directory, then loaded by a runtime

OCI is the distribution mechanism here, not the execution mechanism — the crate ships; a separate runtime opens it.

M4·08

Selective pull — grab only what you need

A warehouse shelved by chapter: the researcher who needs chapter 3 asks for just that box.

ModelKit model (weights) code (scripts) datasets --filter=model --filter=code --filter=datasets Serving node weights only — skips gigabytes CI pipeline lint the inference scripts Data-science notebook analyse data, no weights

The typed-layer manifest is the catalogue — each consumer pulls its box, not the whole book.

M4·09

One artifact, every registry

Same kit push / unpack syntax — only the target reference changes.

ModelKit kit push <ref> GHCR Docker Hub Quay.io Harbor (private) Artifactory local registry:2

TLS by default; add --plain-http for local or air-gapped HTTP-only registries.

M4·10

ModelKit / ORAS vs docker model package

Both pack a GGUF into an OCI artifact — the difference is ecosystem scope.

KitOps ModelKit docker model package CNCF · portable kit — works anywhere any OCI registry typed layers: model/code/data selective pull (--filter) Docker-specific needs Docker Desktop Docker Hub primary single model blob no selective pull

Want portability across registries and runtimes — including Flux into Kubernetes or air-gapped Harbor? Take the CNCF path.

M4·11

TO THE LAB

Ship your model like an image

model code config prompts Registry Serving node

In the lab: pack SmolLM2 + prompts, push to a registry, pull on a clean dir, then selective-pull the weights.

Next up: Lab — Pack & Push a ModelKit with KitOps  ·  Gourav Shah · School of DevOps & AI

M4·12