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 IsDangling(name string) bool
- 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 ReadLayoutTar(r io.Reader, lim Limits) (fs.FS, error)
- func SupportedLayer(mt string) bool
- func ValidateDescriptor(d *Descriptor) error
- type Backend
- type Config
- type Descriptor
- type Digest
- type DirBackend
- func (b *DirBackend) DeleteBlob(hex string) error
- func (b *DirBackend) HasBlob(hex string) bool
- func (b *DirBackend) ListBlobs() ([]string, error)
- func (b *DirBackend) LoadRefs() ([]byte, error)
- func (b *DirBackend) OpenBlob(hex string) (io.ReadCloser, error)
- func (b *DirBackend) PutBlob(hex string, r io.Reader) error
- func (b *DirBackend) SaveRefs(raw []byte) error
- type ExecConfig
- type HealthConfig
- type History
- type Image
- type Index
- type Kind
- type LayoutRef
- type LayoutSource
- type Limits
- type Manifest
- type MemoryBackend
- func (m *MemoryBackend) DeleteBlob(hex string) error
- func (m *MemoryBackend) HasBlob(hex string) bool
- func (m *MemoryBackend) ListBlobs() ([]string, error)
- func (m *MemoryBackend) LoadRefs() ([]byte, error)
- func (m *MemoryBackend) OpenBlob(hex string) (io.ReadCloser, error)
- func (m *MemoryBackend) PutBlob(hex string, r io.Reader) error
- func (m *MemoryBackend) SaveRefs(b []byte) error
- 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) KeepDangling(m Digest) error
- func (s *Store) Names() []NamedRef
- func (s *Store) Open(d Digest) (io.ReadCloser, 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" // MediaTypePkgxLayerZst is a pkgx bottle's layer (go-pkgx/packages). MediaTypePkgxLayerZst = "application/vnd.pkgx.bottle.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>]".
const MaxLayoutEntries = 1 << 14
MaxLayoutEntries bounds the entries of a loaded layout tar.
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 IsDangling ¶ added in v0.12.0
IsDangling reports a name-table entry that only keeps an unnamed image.
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 ReadLayoutTar ¶ added in v0.12.0
ReadLayoutTar reads an OCI image layout sent as a tar (POST /images/load) into memory, as an fs.FS that OpenLayout reads. It is untrusted input: only regular files and directories under relative, clean names are accepted (no links, no "..", no absolute or duplicate names), and the whole is bounded by lim.MaxImageBytes, each file by lim.MaxBlobBytes. Nothing is read from or written to the host's file system.
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 Backend ¶ added in v0.2.0
type Backend interface {
OpenBlob(hex string) (io.ReadCloser, error)
HasBlob(hex string) bool
PutBlob(hex string, r io.Reader) error
DeleteBlob(hex string) error
ListBlobs() ([]string, error)
// LoadRefs returns the saved name table, nil when there is none.
LoadRefs() ([]byte, error)
SaveRefs(b []byte) error
}
Backend is where a Store keeps bytes: a directory on disk natively, a map in memory, or the browser's IndexedDB in the playground. Blobs are named by the encoded part of their sha256 digest; the Store has always verified a blob before PutBlob, and PutBlob must not make a blob visible unless its reader reached EOF without error (it is a verifying reader).
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"`
History []History `json:"history,omitempty"`
// 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 DirBackend ¶ added in v0.2.0
type DirBackend struct {
// contains filtered or unexported fields
}
DirBackend keeps blobs in a directory:
blobs/sha256/<hex> verified content, written once by rename refs.json the name table
func NewDirBackend ¶ added in v0.2.0
func NewDirBackend(root string) (*DirBackend, error)
NewDirBackend creates (if needed) and opens a directory backend.
func (*DirBackend) DeleteBlob ¶ added in v0.2.0
func (b *DirBackend) DeleteBlob(hex string) error
DeleteBlob implements Backend.
func (*DirBackend) HasBlob ¶ added in v0.2.0
func (b *DirBackend) HasBlob(hex string) bool
HasBlob implements Backend.
func (*DirBackend) ListBlobs ¶ added in v0.2.0
func (b *DirBackend) ListBlobs() ([]string, error)
ListBlobs implements Backend.
func (*DirBackend) LoadRefs ¶ added in v0.2.0
func (b *DirBackend) LoadRefs() ([]byte, error)
LoadRefs implements Backend.
func (*DirBackend) OpenBlob ¶ added in v0.2.0
func (b *DirBackend) OpenBlob(hex string) (io.ReadCloser, error)
OpenBlob implements Backend.
func (*DirBackend) PutBlob ¶ added in v0.2.0
func (b *DirBackend) PutBlob(hex string, r io.Reader) error
PutBlob implements Backend: the content reaches its final name only by rename, after the reader reached EOF without error.
func (*DirBackend) SaveRefs ¶ added in v0.2.0
func (b *DirBackend) SaveRefs(raw []byte) error
SaveRefs implements Backend, by rename.
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"`
// Docker's extensions to the OCI config, kept so that an image built
// elsewhere round-trips and `commit` can set them.
ArgsEscaped bool `json:"ArgsEscaped,omitempty"`
Shell []string `json:"Shell,omitempty"`
OnBuild []string `json:"OnBuild,omitempty"`
Healthcheck *HealthConfig `json:"Healthcheck,omitempty"`
}
ExecConfig is the "config" object of an image config: how to run it.
type HealthConfig ¶ added in v0.12.0
type HealthConfig struct {
Test []string `json:"Test,omitempty"`
Interval int64 `json:"Interval,omitempty"`
Timeout int64 `json:"Timeout,omitempty"`
StartPeriod int64 `json:"StartPeriod,omitempty"`
StartInterval int64 `json:"StartInterval,omitempty"`
Retries int `json:"Retries,omitempty"`
}
HealthConfig is Docker's HEALTHCHECK (durations in nanoseconds).
type History ¶ added in v0.12.0
type History struct {
Created string `json:"created,omitempty"`
CreatedBy string `json:"created_by,omitempty"`
Author string `json:"author,omitempty"`
Comment string `json:"comment,omitempty"`
EmptyLayer bool `json:"empty_layer,omitempty"`
}
History is one entry of an image's history (image-spec config.md).
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 MemoryBackend ¶ added in v0.2.0
type MemoryBackend struct {
// MaxBytes bounds the total blob bytes (0 = unlimited).
MaxBytes int64
// contains filtered or unexported fields
}
MemoryBackend keeps everything in memory, bounded by MaxBytes.
func NewMemoryBackend ¶ added in v0.2.0
func NewMemoryBackend(maxBytes int64) *MemoryBackend
NewMemoryBackend returns an empty memory backend.
func (*MemoryBackend) DeleteBlob ¶ added in v0.2.0
func (m *MemoryBackend) DeleteBlob(hex string) error
DeleteBlob implements Backend.
func (*MemoryBackend) HasBlob ¶ added in v0.2.0
func (m *MemoryBackend) HasBlob(hex string) bool
HasBlob implements Backend.
func (*MemoryBackend) ListBlobs ¶ added in v0.2.0
func (m *MemoryBackend) ListBlobs() ([]string, error)
ListBlobs implements Backend.
func (*MemoryBackend) LoadRefs ¶ added in v0.2.0
func (m *MemoryBackend) LoadRefs() ([]byte, error)
LoadRefs implements Backend.
func (*MemoryBackend) OpenBlob ¶ added in v0.2.0
func (m *MemoryBackend) OpenBlob(hex string) (io.ReadCloser, error)
OpenBlob implements Backend.
func (*MemoryBackend) PutBlob ¶ added in v0.2.0
func (m *MemoryBackend) PutBlob(hex string, r io.Reader) error
PutBlob implements Backend: the blob is published only after the whole (verifying) reader was consumed without error.
func (*MemoryBackend) SaveRefs ¶ added in v0.2.0
func (m *MemoryBackend) SaveRefs(b []byte) error
SaveRefs implements Backend.
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
// Mirrors maps a reference's domain ("docker.io" for familiar names)
// to the base URL that serves its /v2 API, which may carry a path
// prefix: "https://example.org/playground" makes "hello" resolve to
// https://example.org/playground/v2/library/hello/manifests/latest.
Mirrors map[string]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 with a table of names.
A blob only ever becomes visible 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.
func (*Store) KeepDangling ¶ added in v0.12.0
KeepDangling keeps an unnamed image (by its manifest) from the GC, unless a name already has it.
func (*Store) Open ¶
func (s *Store) Open(d Digest) (io.ReadCloser, error)
Open opens a stored blob.