# How Container Integrates with OCI Registries for Image Pull and Push

> Discover how Container integrates with OCI registries. Learn how its Swift architecture converts CLI commands into OCI Distribution Specification HTTP calls for seamless image pull and push operations.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: how-to-guide
- Published: 2026-07-11

---

**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`](https://github.com/apple/container/blob/main/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`](https://github.com/apple/container/blob/main/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`](https://github.com/apple/container/blob/main/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

```swift
// 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`](https://github.com/apple/container/blob/main/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

```swift
// 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`](https://github.com/apple/container/blob/main/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`.

```swift
// 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`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Registry/RegistryLogout.swift) command removes these stored credentials, while [`RegistryList.swift`](https://github.com/apple/container/blob/main/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`](https://github.com/apple/container/blob/main/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.

```swift
// 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`](https://github.com/apple/container/blob/main/RegistryLogin.swift) (lines 63–68).
- Registry hostnames are validated against `Reference.domainPattern` in [`RegistryResource.swift`](https://github.com/apple/container/blob/main/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`](https://github.com/apple/container/blob/main/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`](https://github.com/apple/container/blob/main/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.