Documentation
¶
Overview ¶
Package image is the OCI content side of the engine: content-addressed blobs, manifests, indexes and configs, pulled from an OCI image layout or an OCI distribution registry and kept in a local store.
Everything that arrives from outside is treated as hostile: every read is bounded, every blob is verified against its digest before it is used, and every document is validated before it is trusted.
Index ¶
- Constants
- Variables
- func CheckPlatform(c *Config) error
- func IsIndexType(mt string) bool
- func IsLayoutRef(s string) bool
- func IsManifestType(mt string) bool
- func NewVerifyingReader(r io.Reader, d Digest, size int64) io.Reader
- func NormalizeName(s string) (string, error)
- func ParseChallenge(h string) (scheme string, params map[string]string)
- func SupportedLayer(mt string) bool
- func ValidateDescriptor(d *Descriptor) error
- type Config
- type Descriptor
- type Digest
- type ExecConfig
- type Image
- type Index
- type Kind
- type LayoutRef
- type LayoutSource
- type Limits
- type Manifest
- type NamedRef
- type Platform
- type Progress
- type PullResult
- type Ref
- type Reference
- type RegistryError
- type RegistryOptions
- type RegistrySource
- type RootFS
- type Source
- type Store
- func (s *Store) GC(lim Limits) ([]Digest, error)
- func (s *Store) Has(d Digest) bool
- func (s *Store) Image(manifest Digest, lim Limits) (*Image, error)
- func (s *Store) Ingest(desc Descriptor, r io.Reader) error
- func (s *Store) Names() []NamedRef
- func (s *Store) Open(d Digest) (*os.File, error)
- func (s *Store) ReadBlob(d Digest, max int64) ([]byte, error)
- func (s *Store) Resolve(name string) (Ref, bool)
- func (s *Store) Tag(name string, r Ref) error
- func (s *Store) Untag(name string) (bool, error)
Constants ¶
const ( DefaultDomain = "docker.io" DefaultTag = "latest" // DockerHubRegistry is the host that actually serves docker.io. DockerHubRegistry = "registry-1.docker.io" )
Docker Hub normalisation, as github.com/distribution/reference does it (normalize.go, splitDockerDomain).
const ( MediaTypeOCIManifest = "application/vnd.oci.image.manifest.v1+json" MediaTypeOCIIndex = "application/vnd.oci.image.index.v1+json" MediaTypeOCIConfig = "application/vnd.oci.image.config.v1+json" MediaTypeOCILayer = "application/vnd.oci.image.layer.v1.tar" MediaTypeOCILayerGz = "application/vnd.oci.image.layer.v1.tar+gzip" MediaTypeOCILayerZst = "application/vnd.oci.image.layer.v1.tar+zstd" MediaTypeDockerManifest = "application/vnd.docker.distribution.manifest.v2+json" MediaTypeDockerList = "application/vnd.docker.distribution.manifest.list.v2+json" MediaTypeDockerConfig = "application/vnd.docker.container.image.v1+json" MediaTypeDockerLayerGz = "application/vnd.docker.image.rootfs.diff.tar.gzip" MediaTypeWasmConfig = "application/vnd.wasm.config.v0+json" MediaTypeWasmLayer = "application/wasm" )
Media types the engine understands. The OCI ones come from the image specification, the wasm ones from the CNCF TAG-Runtime Wasm OCI artifact layout, and the Docker ones are the schema 2 types that registries still serve for images built by Docker.
const ( AnnotationRefName = "org.opencontainers.image.ref.name" AnnotationTitle = "org.opencontainers.image.title" )
Annotation keys used by the engine.
const LayoutPrefix = "oci:"
LayoutPrefix marks an OCI image layout reference: "oci:<dir>[:<ref.name>]".
Variables ¶
var DefaultLimits = Limits{
MaxManifestBytes: 4 << 20,
MaxConfigBytes: 4 << 20,
MaxBlobBytes: 512 << 20,
MaxLayers: 128,
MaxIndexEntries: 1024,
MaxImageBytes: 1 << 30,
}
DefaultLimits are generous for wasm images and small for anything else.
var ErrDigest = errors.New("digest")
ErrDigest is wrapped by every digest syntax or verification failure.
var ErrInvalid = errors.New("invalid OCI document")
ErrInvalid is wrapped by every validation failure of a document.
var ErrNoPlatform = fmt.Errorf("no matching manifest for %s in the index", WasmPlatform)
ErrNoPlatform is returned when an index has no manifest the engine runs.
var ErrNotFound = errors.New("not found")
ErrNotFound is wrapped when a blob or a name is not in the store.
var ErrTooLarge = errors.New("content too large")
ErrTooLarge is wrapped when content exceeds its declared size or a limit.
var WasmPlatform = Platform{OS: "wasip1", Architecture: "wasm"}
WasmPlatform is the only platform the engine runs.
Functions ¶
func CheckPlatform ¶
CheckPlatform refuses a config that is not for wasip1/wasm.
func IsIndexType ¶
IsIndexType reports whether mt names an image index.
func IsLayoutRef ¶
IsLayoutRef reports whether s names an OCI image layout.
func IsManifestType ¶
IsManifestType reports whether mt names an image manifest.
func NewVerifyingReader ¶
NewVerifyingReader wraps r so that reading it to EOF proves it is exactly size bytes with digest d. Reading fails with ErrTooLarge as soon as a byte past size is seen, and with ErrDigest at EOF when the content differs.
func NormalizeName ¶
NormalizeName returns the familiar "name:tag" (or "name@digest") a store keys images by.
func ParseChallenge ¶
ParseChallenge parses `Bearer realm="…",service="…",scope="…"`.
func SupportedLayer ¶
SupportedLayer reports whether the engine can unpack a layer media type.
func ValidateDescriptor ¶
func ValidateDescriptor(d *Descriptor) error
ValidateDescriptor checks a descriptor's required fields.
Types ¶
type Config ¶
type Config struct {
Created string `json:"created,omitempty"`
Author string `json:"author,omitempty"`
Architecture string `json:"architecture"`
OS string `json:"os"`
Variant string `json:"variant,omitempty"`
Config ExecConfig `json:"config"`
RootFS RootFS `json:"rootfs"`
// LayerDigests is the wasm artifact's list of layer digests.
LayerDigests []string `json:"layerDigests,omitempty"`
}
Config is an OCI image config, or a CNCF wasm artifact config: the two share created/author/architecture/os, and each ignores the other's extra fields.
type Descriptor ¶
type Descriptor struct {
MediaType string `json:"mediaType"`
Digest Digest `json:"digest"`
Size int64 `json:"size"`
URLs []string `json:"urls,omitempty"`
Annotations map[string]string `json:"annotations,omitempty"`
Data []byte `json:"data,omitempty"`
Platform *Platform `json:"platform,omitempty"`
ArtifactType string `json:"artifactType,omitempty"`
}
Descriptor points at content by digest and size.
func SelectManifest ¶
func SelectManifest(x *Index, want Platform) (Descriptor, error)
SelectManifest picks the wasip1/wasm image manifest of an index. Entries that are not image manifests (attestations, nested indexes, unknown types) are skipped, as image-index.md requires of unknown media types.
type Digest ¶
type Digest string
Digest is a validated content identifier, "sha256:<64 lower-case hex>".
Only sha256 is accepted: descriptor.md makes it the one algorithm an implementation MUST support, and refusing the rest keeps the set of strings that can become a file name in the store closed.
func ParseDigest ¶
ParseDigest validates s and returns it as a Digest.
type ExecConfig ¶
type ExecConfig struct {
User string `json:"User,omitempty"`
ExposedPorts map[string]struct{} `json:"ExposedPorts,omitempty"`
Env []string `json:"Env,omitempty"`
Entrypoint []string `json:"Entrypoint,omitempty"`
Cmd []string `json:"Cmd,omitempty"`
Volumes map[string]struct{} `json:"Volumes,omitempty"`
WorkingDir string `json:"WorkingDir,omitempty"`
Labels map[string]string `json:"Labels,omitempty"`
StopSignal string `json:"StopSignal,omitempty"`
}
ExecConfig is the "config" object of an image config: how to run it.
type Image ¶
type Image struct {
ManifestDigest Digest
Manifest *Manifest
ConfigDigest Digest
Config *Config
// Size is the total size of the config and layer blobs.
Size int64
// Wasm reports a CNCF wasm artifact (single application/wasm layer).
Wasm bool
}
Image is a pulled image as the store knows it: one platform manifest, its config, and the names that refer to it.
type Index ¶
type Index struct {
SchemaVersion int `json:"schemaVersion"`
MediaType string `json:"mediaType,omitempty"`
ArtifactType string `json:"artifactType,omitempty"`
Manifests []Descriptor `json:"manifests"`
Subject *Descriptor `json:"subject,omitempty"`
Annotations map[string]string `json:"annotations,omitempty"`
}
Index is an OCI image index (or a Docker manifest list).
type LayoutRef ¶
type LayoutRef struct {
Dir string
// RefName selects the index.json entry whose
// org.opencontainers.image.ref.name annotation equals it; empty means
// "the only entry".
RefName string
}
LayoutRef is a parsed layout reference.
func ParseLayoutRef ¶
ParseLayoutRef parses "oci:<dir>[:<ref.name>]". The ref name is what follows the last colon when it contains no slash, so a directory may hold colons as long as a ref name is given.
type LayoutSource ¶
type LayoutSource struct {
// contains filtered or unexported fields
}
LayoutSource reads an OCI image layout through an fs.FS.
func OpenLayout ¶
OpenLayout opens a layout and checks its oci-layout marker.
func OpenLayoutDir ¶
func OpenLayoutDir(r LayoutRef, lim Limits) (*LayoutSource, error)
OpenLayoutDir opens the layout directory a LayoutRef names.
func (*LayoutSource) Fetch ¶
func (l *LayoutSource) Fetch(_ context.Context, d Descriptor) (io.ReadCloser, error)
Fetch implements Source.
func (*LayoutSource) Index ¶
func (l *LayoutSource) Index() (*Index, error)
Index reads and validates index.json.
func (*LayoutSource) Resolve ¶
func (l *LayoutSource) Resolve(context.Context) (Descriptor, error)
Resolve implements Source.
type Limits ¶
type Limits struct {
// MaxManifestBytes bounds a manifest or an index document.
MaxManifestBytes int64
// MaxConfigBytes bounds an image config.
MaxConfigBytes int64
// MaxBlobBytes bounds one layer blob as stored (compressed).
MaxBlobBytes int64
// MaxLayers bounds the number of layers of one manifest.
MaxLayers int
// MaxIndexEntries bounds the number of manifests of an index.
MaxIndexEntries int
// MaxImageBytes bounds the sum of an image's blob sizes.
MaxImageBytes int64
}
Limits bounds what a pull may make the engine read and keep.
type Manifest ¶
type Manifest struct {
SchemaVersion int `json:"schemaVersion"`
MediaType string `json:"mediaType,omitempty"`
ArtifactType string `json:"artifactType,omitempty"`
Config Descriptor `json:"config"`
Layers []Descriptor `json:"layers"`
Subject *Descriptor `json:"subject,omitempty"`
Annotations map[string]string `json:"annotations,omitempty"`
}
Manifest is an OCI image manifest (or a Docker schema 2 manifest, which has the same shape).
type Platform ¶
type Platform struct {
Architecture string `json:"architecture"`
OS string `json:"os"`
OSVersion string `json:"os.version,omitempty"`
OSFeatures []string `json:"os.features,omitempty"`
Variant string `json:"variant,omitempty"`
}
Platform is the platform of a manifest in an index.
type Progress ¶
type Progress func(id, status string)
Progress receives human-readable status lines during a pull, keyed by a short id (a digest prefix, or "" for the image as a whole).
type PullResult ¶
type PullResult struct {
Image *Image
// RepoDigest is the digest the reference resolved to.
RepoDigest Digest
// Downloaded reports whether any blob was new to the store.
Downloaded bool
}
PullResult describes a completed pull.
type Ref ¶
type Ref struct {
// Manifest is the platform image manifest.
Manifest Digest `json:"manifest"`
// RepoDigest is the digest the name resolved to at pull time (an index
// or the manifest itself).
RepoDigest Digest `json:"repoDigest,omitempty"`
}
Ref is what a name points at.
type Reference ¶
Reference is a parsed image reference: domain/path[:tag][@digest].
func ParseReference ¶
ParseReference parses and normalises s ("hello" becomes docker.io/library/hello:latest). A reference with neither tag nor digest gets the tag "latest".
func (Reference) Name ¶
Name is the familiar repository name: docker.io/library/x is "x", docker.io/u/x is "u/x", anything else keeps its domain.
func (Reference) Object ¶
Object is what the registry is asked for: the digest if any, else the tag.
func (Reference) RegistryHost ¶
RegistryHost is the host to contact for r.
type RegistryError ¶
RegistryError is a non-success answer from a registry.
func (*RegistryError) Error ¶
func (e *RegistryError) Error() string
func (*RegistryError) Is ¶
func (e *RegistryError) Is(target error) bool
Is lets errors.Is(err, ErrNotFound) match a 404.
type RegistryOptions ¶
type RegistryOptions struct {
// Client is the HTTP client; nil means a default one. Its CheckRedirect
// is replaced so Authorization never crosses hosts.
Client *http.Client
// Insecure lists registry hosts reached over plain HTTP. Loopback hosts
// (localhost, 127.0.0.0/8, ::1) are always plain HTTP, as Docker does.
Insecure []string
// UserAgent is sent on every request.
UserAgent string
}
RegistryOptions configures a registry source.
type RegistrySource ¶
type RegistrySource struct {
// contains filtered or unexported fields
}
RegistrySource pulls one reference from an OCI distribution registry.
func NewRegistrySource ¶
func NewRegistrySource(ref Reference, opt RegistryOptions, lim Limits) *RegistrySource
NewRegistrySource prepares a pull of ref.
func (*RegistrySource) Fetch ¶
func (r *RegistrySource) Fetch(ctx context.Context, d Descriptor) (io.ReadCloser, error)
Fetch implements Source.
func (*RegistrySource) Resolve ¶
func (r *RegistrySource) Resolve(ctx context.Context) (Descriptor, error)
Resolve implements Source: it fetches the manifest or index the reference names, verifies it, and returns it inline in Data.
type Source ¶
type Source interface {
// Resolve returns the descriptor of the reference the source was opened
// for: an index or a manifest. It may carry the content in Data.
Resolve(ctx context.Context) (Descriptor, error)
// Fetch returns the content of d.
Fetch(ctx context.Context, d Descriptor) (io.ReadCloser, error)
}
Source is somewhere images come from: a registry repository or an OCI image layout. Nothing a Source returns is trusted; Pull verifies it.
func OpenSource ¶
OpenSource turns a pull reference into a Source and the local name the pulled image is stored under. "oci:<dir>[:<ref.name>]" opens an OCI image layout; anything else is a registry reference.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is a content-addressed blob store on disk with a table of names.
Layout under root:
blobs/sha256/<hex> verified content, written once by rename refs.json name -> manifest digest
A blob only ever reaches its final path after its size and digest were checked, so anything found there can be trusted to be what its name says.
func (*Store) Ingest ¶
func (s *Store) Ingest(desc Descriptor, r io.Reader) error
Ingest copies the content desc names from r into the store, verifying its size and digest. desc.Size must already have been checked against a limit by the caller.