How Apple Container Achieves OCI Image Compatibility with Other Runtimes
Apple Container ensures OCI image compatibility by routing every image operation through the ContainerizationOCI library, which strictly implements the OCI Image Specification types, validation logic, and storage layout.
The apple/container project implements a Swift-based container runtime built atop the Containerization open-source stack. By delegating all image parsing, validation, and storage to a dedicated OCI-aware library, the runtime delivers complete OCI image compatibility, enabling seamless consumption of images from Docker, Podman, and BuildKit while producing images that any OCI-compliant runtime can execute.
The ContainerizationOCI Library Foundation
All image-related operations in container funnel through ContainerizationOCI, a Swift package declared in Package.swift (lines 92–112). This library implements the verbatim OCI Image Specification, providing strongly-typed representations of Image, Manifest, Platform, and Reference. According to docs/technical-overview.md (lines 20–33), the codebase explicitly “consumes and produces standard OCI images”, making interoperability a foundational design constraint rather than an afterthought.
By centralizing image handling in this library, container guarantees that every manifest, config, and layer blob adheres to the canonical OCI schema before touching the network or storage.
Strict Reference Parsing and Validation
Before any network request, user-supplied image strings undergo rigid validation to ensure they conform to OCI reference grammar.
Reference Grammar Enforcement
In Sources/ContainerCommands/Image/ImageList.swift (line 123), CLI commands invoke ContainerizationOCI.Reference.parse to transform text like docker.io/library/ubuntu:22.04 into a structured object. This routine validates the name, tag, and optional digest components, rejecting malformed references before they reach the content store.
Registry Hostname Validation
When adding a new registry endpoint, Sources/ContainerResource/Registry/RegistryResource.swift (lines 52–70) applies nameValid(_:), which uses the exact regular-expression pattern defined by the OCI distribution specification. This includes support for IPv6 literals and optional ports, preventing ill-formed registry URLs from being persisted.
Platform-Aware Image Resolution
OCI images frequently bundle multi-architecture manifests. To ensure the correct variant is executed, Sources/ContainerBuild/BuildImageResolver.swift (lines 24–30 and 94–98) extracts the Platform (OS, architecture, variant) from the manifest and retrieves the matching ContainerizationOCI.Image payload. This guarantees that the image handed to the VM matches the requested platform, following the same resolution logic used by Docker and Podman.
Canonical OCI Storage Layout
container stores image blobs in an unchanged, canonical OCI layout: raw compressed layers, config JSON, and manifests are written to blobs/sha256/... with an accompanying index.json. Because the content store preserves the exact bytes received from registries, other runtimes reading these files encounter a standard OCI directory layout that requires no translation. Conversely, when container pulls from a Docker registry, it writes layers verbatim, ensuring that Docker-created images load without modification.
Cross-Runtime Export and Import
The container image save command generates tarballs that follow the OCI Image Layout specification. Internally, this executes ImageResource.save, which organizes the archive exactly as defined by the OCI standard. These tarballs can be imported directly using docker load or podman load. Similarly, container image load accepts OCI-layout tarballs from any source, verifying the manifest schema before acceptance, ensuring bidirectional compatibility.
Practical Implementation Examples
Building an OCI-Compliant Image
import ContainerizationOCI
import ContainerBuild
let builder = try Builder(
contentStore: store,
config: .init(),
containerSystemConfig: systemConfig
)
// Parse and pull a base image using OCI reference syntax
let baseRef = try ContainerizationOCI.Reference.parse("docker.io/library/ubuntu:22.04")
let baseImage = try await builder.pull(reference: baseRef, platform: .current)
// Add a layer and commit
let layer = try Layer(contentsOf: URL(fileURLWithPath: "./myapp"))
try builder.add(layer: layer, to: baseImage)
let newImage = try await builder.commit(
from: baseImage,
tag: "myorg/myapp:latest",
platform: .current
)
Pulling from Any OCI Registry
import ContainerizationOCI
import ContainerAPIClient
let ref = try ContainerizationOCI.Reference.parse("ghcr.io/apple/example:1.2.3")
let platform = ContainerizationOCI.Platform.current
// Fetches from cache or network, returns a spec-compliant Image object
let image = try await ClientImage.fetch(
reference: ref,
platform: platform,
containerSystemConfig: config,
progressUpdate: { /* handle progress */ }
)
print("Config digest: \(image.config.digest)")
Exporting for Other Runtimes
import ContainerCommands
// Creates an OCI-layout tarball compatible with docker load
try ImageResource.save(
image: myImage,
to: URL(fileURLWithPath: "./myapp-oci.tar")
)
Summary
- ContainerizationOCI Library: Centralizes all image handling in a spec-compliant Swift package defined in
Package.swift, ensuring every operation implements the OCI Image Specification. - Strict Validation:
ContainerizationOCI.Reference.parseandRegistryResource.nameValid(_:)enforce OCI grammar and hostname rules before storage. - Platform Resolution:
BuildImageResolverextracts the correct multi-arch manifest platform, matching the behavior of Docker and Podman. - Canonical Storage: Blobs are stored in the standard
blobs/sha256layout, allowing other runtimes to readcontainer’s store directly. - Interchangeable Export:
ImageResource.saveproduces OCI Image Layout tarballs that import cleanly into any OCI-compatible runtime.
Frequently Asked Questions
What library provides OCI compatibility in Apple Container?
The ContainerizationOCI Swift package, declared as a dependency in Package.swift (lines 92–112), provides all OCI types and validation logic. Every image operation—parsing, building, pulling, and exporting—routes through this library to guarantee spec compliance.
Can container run images built with Docker or Podman?
Yes. Because container stores image layers, manifests, and configs in the canonical OCI layout without modification, it can execute images created by Docker, Podman, BuildKit, or any OCI-compliant tool. The content store at blobs/sha256/... is readable by any runtime that supports the OCI Image Specification.
How does container handle multi-architecture images?
container uses BuildImageResolver (Sources/ContainerBuild/BuildImageResolver.swift, lines 94–98) to inspect OCI manifest lists, extract the Platform object matching the host OS and architecture, and fetch the corresponding image configuration. This ensures the correct binary variant is executed, identical to the platform selection logic in Docker.
What storage format does container use for images?
container uses the OCI Image Layout format, storing blobs under blobs/sha256/ with an index.json index file. This canonical layout means the on-disk representation is immediately readable by other OCI tools without conversion or export.
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 →