Open-Source Wikis

/

containerd

/

Systems

/

Image distribution

containerd/containerd

Image distribution

How containerd pulls, pushes, imports, exports, and unpacks images. Spread across core/remotes/, core/images/, core/transfer/, core/unpack/, and the transfer plugin.

Purpose

  • Talk to OCI distribution registries (Docker registry v2 protocol, OCI distribution-spec).
  • Stream layers into the content store with resumption and parallelism.
  • Materialize image layers as committed snapshots in a chosen snapshotter ("unpack").
  • Provide a higher-level transfer API that bundles pull/push/import/export in a single streaming gRPC call.

Pieces

Piece Code Role
Resolver core/remotes/, core/remotes/docker/ Resolves a reference (docker.io/library/alpine:3) to a Resolver capable of fetching/pushing
Auth core/remotes/docker/auth/, pkg/oci/ Handles bearer tokens, basic auth, dockerconfig
Hosts core/remotes/docker/config/ hosts.toml mirror configuration (per-host TLS, capabilities, mirrors)
Image store core/images/, core/metadata/images.go Image records: name → root descriptor
Unpack core/unpack/ Walks a manifest, pulls each layer, applies it to a snapshotter
Differ core/diff/, plugins/diff/walking/ Computes / applies layer diffs
Transfer core/transfer/, plugins/transfer/ High-level streaming pipeline that exposes pull/push/import/export over a single gRPC stream

Pull flow

sequenceDiagram
    autonumber
    participant Client
    participant TransferSvc as Transfer service
    participant Resolver as remotes.Resolver
    participant Content as Content store
    participant Unpack as unpack pipeline
    participant Snap as Snapshotter
    participant Meta as Metadata

    Client->>TransferSvc: Transfer(Pull{ref, unpack=true})
    TransferSvc->>Resolver: Resolve(ref)
    Resolver-->>TransferSvc: Descriptor, Fetcher
    TransferSvc->>Content: ingest manifest
    TransferSvc->>Content: ingest config
    TransferSvc->>Content: ingest layers (parallel)
    TransferSvc->>Unpack: Unpack(image, snapshotter)
    Unpack->>Snap: Prepare each layer
    Unpack->>Snap: Apply diff
    Unpack->>Snap: Commit
    TransferSvc->>Meta: store image
    TransferSvc-->>Client: Progress events

Resolver

core/remotes/docker/resolver.go implements remotes.Resolver:

type Resolver interface {
    Resolve(ctx context.Context, ref string) (name string, desc ocispec.Descriptor, err error)
    Fetcher(ctx context.Context, ref string) (Fetcher, error)
    Pusher(ctx context.Context, ref string) (Pusher, error)
}

The Docker resolver speaks the registry v2 HTTP API. It uses core/remotes/docker/config/ to read host overrides from hosts.toml (mirror lists, scheme, TLS) and core/remotes/docker/auth/ to handle Bearer/Basic auth.

Hosts.toml

docs/hosts.md describes the registry config format. Common fields:

server = "https://my-private-registry.example.com"

[host."https://mirror1.example.com"]
  capabilities = ["pull", "resolve"]
  skip_verify = false

The config is read on-demand per registry. See core/remotes/docker/config/hosts.go.

Unpacking

core/unpack/unpacker.go orchestrates layer extraction:

  1. Read the manifest from the content store.
  2. For each layer (in order), Prepare a new snapshot whose parent is the previous layer's commit.
  3. Run the differ to apply the layer's tar stream onto the prepared snapshot.
  4. Commit the snapshot under a content-derived name (uncompressed digest).
  5. Repeat until the manifest is exhausted.

The differ is pluggable via the DiffPlugin type — walking (the default) walks the layer tar; erofs, windows, and lcow provide platform-specific paths.

Transfer service

The transfer service is the modern entry point. Clients send a single streaming Transfer RPC carrying:

  • A source (OCIRegistry, ImageStore, Importer, …)
  • A destination (ImageStore, OCIRegistry, Exporter, …)
  • Optional filters/transformations

The plugin in plugins/transfer/ registers TransferPlugin builtins for the supported source/destination types; core/transfer/ defines the interfaces.

The newer transfer service supersedes direct use of the Images / Content gRPC services for pulls and pushes from clients that don't need fine-grained control.

Push flow

The mirror image of pull. Resolver becomes a Pusher; layers are uploaded in parallel; at the end, the manifest is uploaded.

Import / export

ctr image import and ctr image export use the transfer service's Importer/Exporter types, which read/write OCI image layouts (and Docker save/load tarballs).

Image verification

Before an image is committed to the image store, the daemon can run an external verifier. The ImageVerifierPlugin (plugins/imageverifier/bindir) runs configured binaries against each manifest and short-circuits on failure. See docs/image-verification.md.

Entry points for modification

  • New auth scheme: extend core/remotes/docker/auth/.
  • New transport: implement remotes.Resolver and register it from a plugin.
  • New differ: implement core/diff/diff.go's interface and add a plugin under plugins/diff/<name>/.
  • New transfer source/destination: register a TransferPlugin and implement the corresponding core/transfer interface.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Image distribution – containerd wiki | Factory