How Container Implements OCI Image Specification Support for Building and Pulling Images
The container toolchain leverages Apple's ContainerizationOCI library to provide full OCI image specification compliance for building and pulling operations through a layered architecture of CLI commands, async services, and registry-aware storage backends.
The apple/container repository provides a Swift-native container runtime that implements the Open Container Initiative (OCI) image specification for both building and pulling operations. At its core, the toolchain relies on the ContainerizationOCI library, which defines Swift data models for OCI manifests, configurations, and platform descriptors. This architecture enables seamless interoperability with standard OCI registries while providing macOS-integrated authentication and platform-aware image selection.
How OCI Image Pulling Works
The pull operation follows a structured pipeline from CLI parsing to layer verification. The ImagesService class in Sources/Services/ContainerImagesService/Server/ImagesService.swift exposes a thin async façade that implements list, pull, push, tag, and delete operations, delegating heavy lifting to the underlying ImageStore.
OCI Reference Parsing and Validation
When a user executes container images pull docker.io/library/ubuntu:20.04, the CLI first validates the reference string using ContainerizationOCI.Reference.init(_:). This initializer, defined in the ContainerizationOCI library, enforces the domain pattern requirements specified by the OCI distribution specification. The RegistryResource struct in Sources/ContainerResource/Registry/RegistryResource.swift performs additional hostname validation against the OCI distribution spec before establishing connections.
Platform-Aware Manifest Selection
The ImagesService handles platform negotiation through helpers in Sources/ContainerAPIService/Client/DefaultPlatform.swift. When a user specifies --platform linux/arm64, the service constructs a ContainerizationOCI.Platform value to select the matching manifest entry from multi-platform images. If no platform is specified, the system defaults to the current host platform (.current).
Layer Download and Verification
The ImageStore implementation orchestrates the actual download by iterating over the manifest.layers array. For each layer, it performs an HTTP GET request, verifies the SHA256 digest against the manifest, and writes validated blobs to the local content store. Concurrency is controlled by the maxConcurrentDownloads parameter, which defaults to 3 to prevent registry overwhelm. Progress reporting uses TerminalProgress and ProgressBar.swift to provide blob-wise download status.
Authentication Flow
Before initiating transfers, ImagesService.pull wraps the store call with Self.withAuthentication(ref:). This method retrieves credentials from the macOS keychain or from ~/.container/config.json, injecting the appropriate Authorization header into registry requests. The RegistryLogin.swift file in Sources/ContainerCommands/Registry/ handles the credential storage interface.
How OCI Image Building Works
The container build process bootstraps itself using the same OCI infrastructure it ultimately produces. Rather than treating BuildKit as a host-native binary, the system runs BuildKit itself as an OCI container.
Bootstrapping the BuildKit Container
The BuilderStart command in Sources/ContainerCommands/Builder/BuilderStart.swift (lines 94-101) first calls ImagesService.pull to fetch the BuildKit OCI image (typically docker.io/docker/buildkit:latest). After successfully pulling and unpacking this image into a VM-level container, the code invokes startBuildKit (lines 307-309) to launch the BuildKit daemon inside the sandbox.
Build Execution
Once the BuildKit daemon runs inside the VM, the CLI forwards standard docker build commands to it via the containerd shim. BuildKit resolves base images using the same ImagesService layer, processes Dockerfiles according to OCI specifications, and writes resulting image layers back to the local content store as OCI-compliant blobs.
Registry Communication and Validation
The RegistryResource.swift file implements OCI distribution spec compliance by validating registry hostnames and constructing authenticated HTTP requests. It ensures that all push and pull operations follow the OCI distribution specification for manifest and blob endpoints.
Pushing OCI Images
When pushing via container images push myregistry.example.com/myapp:1.0, the ImagesService.push method (lines 17-22 in ImagesService.swift) authenticates to the target registry and calls ImageStore.push. This creates a new manifest referencing existing layer digests (without re-uploading unchanged layers) and pushes both the manifest and config JSON according to OCI spec requirements.
Key Source Files
Sources/Services/ContainerImagesService/Server/ImagesService.swift: Public async façade for image operations (list,pull,push,tag,delete).Sources/ContainerCommands/Builder/BuilderStart.swift: Starts BuildKit by first pulling its OCI image (lines 94-101).Sources/ContainerResource/Registry/RegistryResource.swift: Validates registry hostnames and builds authenticated HTTP requests per OCI distribution spec.Sources/ContainerAPIService/Client/DefaultPlatform.swift: Platform selection logic for multi-architecture OCI manifests.Sources/ContainerResource/Image/ImageResource.swift: Swift representation of OCI image structures usingContainerizationOCI.Image.Sources/ContainerCommands/Registry/RegistryLogin.swift: Handles OCI registry authentication and credential storage.
Summary
- Container implements OCI image specification support through the ContainerizationOCI library, which provides Swift-native models for manifests, configs, and references.
- The ImagesService in
ImagesService.swiftprovides a unified async interface for pull, push, and tag operations, delegating to the ImageStore for OCI-specific logic. - Pulling involves parsing references via
ContainerizationOCI.Reference, platform selection viaDefaultPlatform.swift, and concurrent layer downloads with SHA256 verification. - Building first pulls the BuildKit OCI image using the same
ImagesService.pullpath, then launches the daemon inside a VM to process Dockerfiles into OCI-compliant output. - Authentication integrates with macOS keychain and
~/.container/config.json, while RegistryResource.swift ensures OCI distribution spec compliance for all registry communications.
Frequently Asked Questions
How does container validate OCI image references?
The toolchain uses ContainerizationOCI.Reference.init(_:) to parse reference strings like docker.io/library/ubuntu:20.04@sha256:..., enforcing the domain pattern defined by the OCI distribution specification. Additional validation occurs in RegistryResource.swift, which verifies that registry hostnames conform to OCI standards before establishing HTTP connections.
What authentication methods does container support for OCI registries?
The ImagesService authenticates via Self.withAuthentication(ref:), which retrieves credentials from the macOS keychain or from the ~/.container/config.json configuration file. The RegistryLogin.swift command handles the credential storage interface, allowing users to log in to registries using standard CLI commands.
How does container handle multi-platform OCI images?
When pulling, the service checks ContainerizationOCI.Platform helpers in DefaultPlatform.swift to select the appropriate manifest entry matching the requested platform (e.g., linux/arm64). If no platform is specified, the system defaults to the current host platform, ensuring architecture-appropriate images are retrieved from multi-arch manifests.
What is the role of BuildKit in the container build process?
BuildKit runs as an OCI container itself, fetched via ImagesService.pull in BuilderStart.swift (lines 94-101). After unpacking the BuildKit image into a VM-level container, the system launches the daemon inside the sandbox. The CLI then forwards build contexts to this daemon, which resolves base OCI images and produces new OCI-compliant image layers according to Dockerfile instructions.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →