# How apple/container Handles OCI Image Format and Registry Interactions

> Discover how apple/container handles OCI image format using the ContainerizationOCI Swift package and interacts with registries through HTTP endpoints following the OCI Distribution Specification.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: internals
- Published: 2026-07-02

---

**apple/container implements OCI image support through the external ContainerizationOCI Swift package, which models OCI specifications as type-safe structs, while registry interactions follow the OCI Distribution Specification via HTTP endpoints handled in [`RegistryResource.swift`](https://github.com/apple/container/blob/main/RegistryResource.swift).**

The apple/container repository is a Swift-based container runtime developed by Apple that natively supports the Open Container Initiative (OCI) image format. It handles OCI image format and interacts with registries through a layered architecture that separates data modeling, storage, and transport concerns across distinct modules.

## OCI Architecture Overview

### Core Data Models

All OCI-compliant operations in apple/container rely on the **ContainerizationOCI** package. This external dependency provides the foundational types that mirror the OCI image and distribution specifications:

- **`ContainerizationOCI.Image`** – Represents the parsed image configuration
- **`ContainerizationOCI.Manifest`** – Models the OCI manifest JSON structure
- **`ContainerizationOCI.Platform`** – Encodes OS/architecture constraints
- **`ContainerizationOCI.Reference`** – Validates and stores registry names, repositories, and tags

These types are imported throughout the codebase (e.g., `import ContainerizationOCI` in command and service files) to ensure type safety when handling image metadata.

### Layered Implementation

The repository organizes OCI functionality into five distinct layers:

1. **OCI Model Layer** – Defines index, config, manifest, and platform descriptors via the ContainerizationOCI package
2. **Registry Interaction Layer** – Validates hostnames and constructs HTTP requests to OCI distribution endpoints (`/v2/…`) in [`Sources/ContainerResource/Registry/RegistryResource.swift`](https://github.com/apple/container/blob/main/Sources/ContainerResource/Registry/RegistryResource.swift)
3. **Image Storage Layer** – Persists OCI blobs and provides lazy access to configs and layers via [`Sources/ContainerResource/Image/ImageResource.swift`](https://github.com/apple/container/blob/main/Sources/ContainerResource/Image/ImageResource.swift)
4. **Service Layer** – Exposes CRUD APIs for images and containers in [`Sources/Services/ContainerImagesService/Server/ImagesService.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerImagesService/Server/ImagesService.swift)
5. **CLI Commands Layer** – Implements user-facing operations like `ImagePull` and `ImagePush` in `Sources/ContainerCommands/Image/`

## Registry Communication Protocol

### Reference Parsing and Validation

Registry interactions begin in [`Sources/ContainerResource/Registry/RegistryResource.swift`](https://github.com/apple/container/blob/main/Sources/ContainerResource/Registry/RegistryResource.swift). This file validates registry hostnames according to the OCI distribution spec and constructs `ContainerizationOCI.Reference` objects. The `Reference.parse` method converts user-supplied strings (e.g., `ubuntu:22.04`) into structured objects containing the registry host, repository path, and tag or digest.

### The Pull Workflow

When executing [`ImagePull.swift`](https://github.com/apple/container/blob/main/ImagePull.swift), apple/container orchestrates a six-step OCI pull sequence:

1. **Reference parsing** – The CLI invokes `Reference.parse` on the input string
2. **Registry lookup** – `RegistryResource` validates the hostname and builds the request URL (`https://<registry>/v2/<name>/manifests/<reference>`)
3. **Manifest retrieval** – The service layer fetches the `ContainerizationOCI.Manifest`
4. **Platform selection** – The code decodes `ContainerizationOCI.Platform` from the manifest to match the host architecture, falling back to the current platform if parsing fails via [`DefaultPlatform.swift`](https://github.com/apple/container/blob/main/DefaultPlatform.swift)
5. **Config and layer download** – The system downloads `ContainerizationOCI.ImageConfig` and each layer blob, verifying digests and sizes
6. **Cache update** – The `ImageResource` representing the pulled image is persisted to the system's `EntityStore`

### The Push Workflow

The push implementation in [`Sources/ContainerCommands/Image/ImagePush.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Image/ImagePush.swift) reverses the process:

1. **Reference creation** – Builds a `ContainerizationOCI.Reference` from the target registry and tag
2. **Blob upload** – Uploads each layer using the OCI blob upload endpoint (`PUT /v2/<name>/blobs/uploads/<uuid>`)
3. **Manifest upload** – POSTs the completed manifest containing config digests, layer digests, and platform metadata
4. **Artifact linking** – [`MachineBundle.swift`](https://github.com/apple/container/blob/main/MachineBundle.swift) can attach auxiliary OCI artifacts (such as SBOMs) via the OCI *referrers* API

### Authentication Flow

Registry authentication is handled by [`Sources/ContainerCommands/Registry/RegistryLogin.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Registry/RegistryLogin.swift) and [`RegistryLogout.swift`](https://github.com/apple/container/blob/main/RegistryLogout.swift). These commands implement Docker-style token exchange against OCI registry authentication endpoints and store credentials securely in the local keychain. [`RegistryList.swift`](https://github.com/apple/container/blob/main/RegistryList.swift) enumerates configured registries using the same validation logic found in [`RegistryResource.swift`](https://github.com/apple/container/blob/main/RegistryResource.swift).

## Platform-Aware Image Handling

Multi-platform image support relies on `ContainerizationOCI.Platform.current`, which reflects the host OS and architecture. When processing images with platform-specific variants, the code uses `ContainerizationOCI.Platform(from:)` to select the appropriate configuration. If the manifest specifies a different platform than the host, the system attempts to resolve it before falling back to the current platform configuration.

## Practical Code Examples

### Pull an Image

```swift
import ContainerizationOCI
import ContainerCommands

// Pull "ubuntu:22.04" from Docker Hub
let pull = ImagePull()
try await pull.run([
    "--repository", "docker.io/library/ubuntu",
    "--tag", "22.04"
])

```

Internally, `ImagePull` parses the reference, contacts the registry, downloads the manifest, config, and layers, and stores the result as an `ImageResource`.

### Push a Local Image

```swift
import ContainerizationOCI
import ContainerCommands

let push = ImagePush()
try await push.run([
    "--repository", "myregistry.example.com/myimage",
    "--tag", "v1.0"
])

```

This command uploads each layer blob sequentially, then pushes the final manifest to the registry.

### Authenticate to a Registry

```swift
import ContainerCommands

let login = RegistryLogin()
try await login.run([
    "--registry", "myregistry.example.com",
    "--username", "alice"
])

```

`RegistryLogin` performs the OCI token exchange and stores credentials for subsequent operations.

## Summary

- **apple/container** delegates OCI data modeling to the **ContainerizationOCI** package, which provides Swift-native types for `Image`, `Manifest`, `Platform`, and `Reference`
- Registry interactions are centralized in [`Sources/ContainerResource/Registry/RegistryResource.swift`](https://github.com/apple/container/blob/main/Sources/ContainerResource/Registry/RegistryResource.swift), which validates hostnames and constructs OCI-compliant HTTP requests
- Image pulls follow a six-phase workflow from reference parsing through `EntityStore` persistence, coordinated by [`ImagePull.swift`](https://github.com/apple/container/blob/main/ImagePull.swift) and [`ImagesService.swift`](https://github.com/apple/container/blob/main/ImagesService.swift)
- Image pushes upload blobs via `PUT /v2/<name>/blobs/uploads/<uuid>` before POSTing the manifest, with support for OCI referrers in [`MachineBundle.swift`](https://github.com/apple/container/blob/main/MachineBundle.swift)
- Authentication uses Docker-style token exchange implemented in [`RegistryLogin.swift`](https://github.com/apple/container/blob/main/RegistryLogin.swift) and stores credentials in the system keychain

## Frequently Asked Questions

### What OCI specifications does apple/container implement?

apple/container implements the OCI Image Specification for manifests, configs, and layers, alongside the OCI Distribution Specification for registry communication. The `ContainerizationOCI` package provides the underlying data models that conform to these standards.

### How does apple/container authenticate with private registries?

Authentication is handled by [`RegistryLogin.swift`](https://github.com/apple/container/blob/main/RegistryLogin.swift), which performs a Docker-style token exchange with the registry's authentication endpoint. Credentials are stored securely in the local system keychain and retrieved automatically during push and pull operations.

### Can apple/container handle multi-platform OCI images?

Yes. The runtime uses `ContainerizationOCI.Platform` to parse platform descriptors from manifests and selects the appropriate image variant for the host architecture. If a specific platform is requested or the image requires emulation, the system resolves this via [`DefaultPlatform.swift`](https://github.com/apple/container/blob/main/DefaultPlatform.swift) before downloading layers.

### Where does apple/container store OCI images locally?

Downloaded images are persisted as `ImageResource` objects managed by [`ImagesService.swift`](https://github.com/apple/container/blob/main/ImagesService.swift) and stored in the system's `EntityStore`. Blobs are cached locally with verified digests, providing lazy access to image configurations and layers for container creation.