Open-Source Wikis

/

containerd

/

Systems

/

Content store

containerd/containerd

Content store

The content store is a content-addressable blob storage layer that backs every image layer, manifest, and config blob the daemon knows about. The interface lives in core/content/; the default on-disk implementation lives in plugins/content/local/.

Purpose

  • Store immutable blobs keyed by their digest (sha256:...).
  • Serve as the source of truth for image data so that GC can prune blobs whose digests are no longer referenced.
  • Support concurrent ingest with resumability: a pull that's interrupted halfway can resume from the same byte offset.

Directory layout

core/content/
├── adaptor.go        # adapter helpers around the gRPC types
├── content.go        # Store, Manager, Reader, Writer interfaces
├── helpers.go        # WriteBlob, Copy, OpenWriter helpers reused everywhere
├── proxy/            # gRPC client implementing the same Store interface
└── testsuite/        # cross-implementation conformance tests

plugins/content/local/
└── ...               # filesystem-backed implementation

Key abstractions

Type File Purpose
content.Store core/content/content.go Combined Manager + Provider + Ingester interface
content.Manager core/content/content.go Info / Update / Walk / Delete
content.Provider core/content/content.go ReaderAt over a digest
content.Ingester core/content/content.go OpenWriter for new blobs (with optional WithRef resumption)
content.Writer core/content/content.go A staged ingest; Commit(size, digest) finalizes it
helpers.WriteBlob core/content/helpers.go The "do the right thing" helper used by transfer code

On-disk layout

The local plugin (plugins/content/local/) uses two top-level directories under its plugin root:

  • ingest/<random ref>/ — staged writes; contains data (the bytes), total (expected size), ref (the user-provided ref), and startedat/updatedat timestamps. Resumability uses these to re-open a partial blob.
  • blobs/sha256/<digest> — committed blobs, one file per digest. The path is sha256/<digest hex>.

A blob is committed by os.Rename-ing the ingest/<ref>/data file into blobs/sha256/<digest> after verifying the size and digest match.

How a pull writes blobs

graph LR
    Resolver[remotes resolver] -->|HTTP GET layer| Reader
    Reader -->|content.OpenWriter ref=layer| Writer
    Writer -->|Write bytes, periodic Status| Disk[(ingest/&lt;ref&gt;)]
    Reader -->|Commit size,digest| Move[os.Rename]
    Move --> Blob[(blobs/sha256/&lt;digest&gt;)]

The resolver in core/remotes/docker/ opens an HTTP reader for the registry, while helpers.WriteBlob drives the writer. Multiple pulls of the same blob deduplicate via the ref name and the eventual digest commit.

Garbage collection

Each blob carries labels stored alongside it. The metadata GC roots scan walks images and snapshots, marks reachable digests, and the content store deletes anything not in the mark set (and not under a lease). See GC.

Proxying to a remote store

core/content/proxy/ wraps a gRPC ContentClient so that a content store can live in another process. The daemon registers a content proxy plugin from [proxy_plugins.<name>] entries with type = "content" (see plugin runtime).

Service surface

The content gRPC service is implemented by plugins/services/content/ and exposes:

  • Info / Update / Delete / List
  • Read (ReaderAt over a digest, returned as a stream)
  • Write (bidirectional stream for ingest with resumption)
  • Status / ListStatuses / Abort (for inspecting and canceling in-progress ingests)

The proto lives in api/services/content/v1/content.proto.

Entry points for modification

  • New on-disk format: implement content.Store and register it as a built-in or proxy plugin.
  • Custom ingest hashing: see helpers.WriteBlob and the digest.Verifier it constructs.
  • Cross-content-store copy: helpers.Copy is the canonical copy helper, used by transfer.

For the next system in the pipeline, see image distribution.

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

Content store – containerd wiki | Factory