How Container Integrates with OCI Registries for Image Pull and Push

Container integrates with OCI registries through a layered Swift architecture that converts CLI commands into OCI Distribution Specification HTTP calls via the ContainerizationOCI library and RegistryClient module.

The apple/container repository implements a complete container runtime that communicates with OCI-compliant registries using standard HTTP/HTTPS protocols. When users execute container image pull or container image push, the system normalizes image references, handles authentication via the macOS keychain, and streams layer blobs using the OCI Distribution Specification.

OCI Registry Architecture Overview

The integration follows a clear delegation pattern: CLI Commands → ClientImage → RegistryClient → OCI HTTP API.

The ContainerizationOCI Swift library provides the data models for OCI references, manifests, and configurations, while the ContainerAPIClient module contains the networking logic. This separation allows the command-line interface to focus on user input parsing and progress reporting, while the underlying RegistryClient manages the complexities of registry authentication and blob streaming.

How Image Pull Works

The pull operation begins in Sources/ContainerCommands/Image/ImagePull.swift and delegates through several layers before reaching the registry.

Reference Parsing and Normalization

When a user runs container image pull, the command first calls ClientImage.normalizeReference to resolve short names into fully-qualified OCI references.

In ImagePull.swift at line 77, the code uses ContainerizationOCI.Reference to parse the input into the standard format [scheme]://[host]/[name]@sha256:…. This ensures that ambiguous names like hello-world:latest are expanded into canonical references before any network operations occur.

Scheme Selection and DNS Configuration

The transport scheme (http or https) is determined by the --registry option and the system DNS domain configuration.

At line 75 of ImagePull.swift, the RequestScheme enum selects the appropriate protocol based on ContainerSystemConfig.dns.domain. This allows the tool to automatically handle insecure registries in development environments while defaulting to HTTPS for production deployments.

The Pull Workflow Execution

The actual pull implementation streams manifests and layers from the remote registry to the local image store.

In ImagePull.run() (lines 96–100), the code creates a progress bar and invokes ClientImage.pull(...). This method performs the following OCI-compliant operations:

  • Resolves the manifest for the requested platform using ContainerizationOCI.Manifest
  • Streams each layer blob from the registry using RegistryClient
  • Writes layers to the local image store
  • Unpacks the image into the sandbox using ContainerizationOCI.Image descriptors
// Pull an image for the default platform
$ container image pull docker.io/library/hello-world:latest

// Pull a specific platform (e.g., linux/arm64)
$ container image pull \
    --platform linux/arm64 \
    docker.io/library/alpine:3.18

How Image Push Works

Image push reverses the flow, serializing local images into OCI manifests and uploading them to remote registries.

Push Workflow Implementation

The push command entry point resides in Sources/ContainerCommands/Image/ImagePush.swift.

At line 79, ImagePush.run() retrieves a local ClientImage via ClientImage.get, then calls image.push(platform:…, scheme:…, containerSystemConfig:…, progressUpdate:…). The push operation executes these steps:

  1. Serializes the image config and manifest into OCI format
  2. Uploads each layer blob to the remote registry using RegistryClient
  3. Sends the final manifest via a PUT request to complete the upload
// Push a locally built image to a private registry
$ container image push \
    --platform linux/amd64 \
    myregistry.example.com/myapp:1.0.0

Authentication and Credential Management

Private registry operations require authentication handled through BasicAuthentication and the macOS keychain.

Registry Login Flow

The Sources/ContainerCommands/Registry/RegistryLogin.swift file implements credential storage. Lines 63–68 construct a RegistryClient with a BasicAuthentication payload containing the username and password, then store these credentials securely using KeychainHelper.

// Log in to a private registry using password from stdin
$ echo "$MY_PASSWORD" | container registry login \
    --username "$MY_USER" \
    --password-stdin \
    myregistry.example.com

Credential Storage and Retrieval

The system uses KeychainHelper to persist credentials between commands, eliminating the need to authenticate before every pull or push operation. The Sources/ContainerCommands/Registry/RegistryLogout.swift command removes these stored credentials, while RegistryList.swift displays all authenticated registries.

Registry Utilities and Validation

Helper commands provide utilities for managing registry connections and validating hostnames.

Host Validation

Sources/ContainerResource/Registry/RegistryResource.swift (lines 52–72) implements hostname validation using ContainerizationOCI.Reference.domainPattern. This ensures that user-provided registry addresses conform to OCI specification requirements before attempting network connections.

// List all configured registries and authentication status
$ container registry list

Summary

  • Container uses the ContainerizationOCI library to model OCI-compliant references, manifests, and image configurations.
  • The RegistryClient in ContainerAPIClient handles all HTTP/HTTPS communication with OCI registries according to the Distribution Specification.
  • ImagePull.swift normalizes references at line 77 and executes pulls via ClientImage.pull, which streams blobs and unpacks images locally.
  • ImagePush.swift at line 79 delegates to ClientImage.push to serialize and upload layers and manifests.
  • Authentication uses BasicAuthentication with macOS Keychain storage via RegistryLogin.swift (lines 63–68).
  • Registry hostnames are validated against Reference.domainPattern in RegistryResource.swift (lines 52–72).

Frequently Asked Questions

How does Container handle insecure HTTP registries?

Container selects the transport scheme via RequestScheme at line 75 of ImagePull.swift, which evaluates the --registry option and ContainerSystemConfig.dns.domain to determine whether to use HTTP or HTTPS. This allows connections to insecure registries in controlled development environments while maintaining secure defaults.

Where are registry credentials stored between commands?

Credentials are stored in the macOS keychain using KeychainHelper, as implemented in RegistryLogin.swift lines 63–68. This leverages the system's secure credential storage, allowing subsequent pull and push operations to authenticate automatically without re-entering passwords.

What OCI specification does Container implement for image transfers?

Container implements the OCI Distribution Specification for registry communication and the OCI Image Specification for manifest and layer handling. The ContainerizationOCI library provides Swift models for Reference, Manifest, and Image descriptors that align with these standards.

How does Container resolve platform-specific images during a pull?

During ClientImage.pull, the system resolves the manifest for the requested platform using ContainerizationOCI.Manifest descriptors. Users can specify non-default platforms using the --platform flag (e.g., linux/arm64), which filters the available manifests before layer download begins.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →