How to Pull Container Images with Apple's Container Runtime: A Complete Guide

To pull container images with Apple's container runtime, use the container image pull command followed by the image reference, optionally specifying platform constraints, concurrency limits, and output formatsfunctions.

The apple/container repository provides a full OCI-compatible container runtime that handles image pulling through a coordinated multi-step workflow. When you need to pull container images with Apple's container runtime, the tool orchestrates platform resolution, registry authentication, manifest retrieval, and concurrent layer downloads through both command-line and programmatic interfaces.

Understanding the Pull Workflow

The container image pull command implements a six-stage pipeline that transforms a remote image reference into a locally stored OCI layout. This workflow is orchestrated by the Container API Service, which handles high-level registry communication, while the OCI image store manages local persistence.

Platform Resolution Logic

The runtime determines which platform variant (OS + architecture) to pull using a strict precedence hierarchy defined in DefaultPlatform.resolve within Sources/Services/ContainerAPIService/Client/DefaultPlatform.swift (lines 63-73):

  1. The --platform flag overrides all other selectors when explicitly provided
  2. Separate --os and --arch flags are consulted if --platform is omitted
  3. Environment variable CONTAINER_DEFAULT_PLATFORM serves as the third fallback
  4. Host native platform is used as the final default when no explicit selectors exist

This resolution occurs before any network requests, ensuring the client only downloads layers compatible with the target execution environment.

Registry Connection and Authentication

After platform resolution, the runtime establishes a registry connection using the scheme selector (http, https, or auto, defaulting to auto). The client negotiates TLS certificates, prepares authenticated HTTP headers, and validates the registry endpoint before requesting manifests.

Manifest Retrieval and Layer Download

The client requests the image manifest matching the resolved platform, then proceeds to layer acquisition:

  • Concurrent downloads: Default concurrency is set to 3 parallel downloads
  • Configurable limits: Use --max-concurrent-downloads to tune network utilization
  • Progress reporting: Streams download status via --progress options (auto, none, ansi, plain, or color)

Layers are written directly into the local OCI image store as they arrive, with the final image metadata (configuration, history, and platform information) assembled only after all blobs complete verification.

Pull Command Options and Flags

The container image pull command supports several flags that control the pulling behavior:

  • --platform <os/arch>: Specify exact platform variant (e.g., linux/amd64)
  • --os and --arch: Separate flags for platform components
  • --max-concurrent-downloads <n>: Set parallel download limits (default 3)
  • --progress <style>: Control output formatting (auto, none, ansi, plain, color)
  • --quiet: Suppress progress output, showing only the image name
  • --format <type>: Render results as JSON, YAML, or TOML instead of tabular format

Practical Examples

Basic Image Pull

Pull the latest Alpine Linux image for your current host platform:

container image pull docker.io/library/alpine:latest

Cross-Platform Image Pulling

Pull a specific architecture when running on Apple Silicon but need AMD64 images:

container image pull --platform linux/amd64 docker.io/library/busybox:latest

Alternatively, use separate flags:

container image pull --os linux --arch amd64 docker.io/library/busybox:latest

Optimizing Download Performance

Increase concurrent connections for faster pulls on high-bandwidth networks:

container image pull \
    --max-concurrent-downloads 5 \
    --progress plain \
    docker.io/library/nginx:stable

Programmatic Pull with Swift API

For automation and integration, use the ContainerAPIClient module to pull images programmatically:

import ContainerAPIClient
import ContainerizationOCI
import Logging

let logger = Logger(label: "example")
let client = ContainerAPIClient()

do {
    // Resolve platform using same precedence as CLI
    let platform = try DefaultPlatform.resolve(
        platform: nil,               // no --platform flag
        os: nil,                     // no --os flag
        arch: nil,                   // no --arch flag
        log: logger)

    // Configure pull request
    let request = ContainerAPIClient.PullRequest(
        reference: "docker.io/library/redis:7",
        platform: platform,
        scheme: .auto,               // same as CLI default
        maxConcurrentDownloads: 4,
        progress: .auto)

    // Execute pull
    try await client.pull(request: request)
    logger.info("Image pulled successfully")
} catch {
    logger.error("Pull failed: \(error)")
}

This Swift implementation mirrors the CLI flow: platform resolution via DefaultPlatform.resolve, followed by a PullRequest that passes all options to the underlying client.

Summary

  • Platform resolution follows strict precedence: --platform flag overrides --os/--arch flags, which override the CONTAINER_DEFAULT_PLATFORM environment variable, which falls back to the host native platform (implemented in Sources/Services/ContainerAPIService/Client/DefaultPlatform.swift)
  • Concurrency control defaults to 3 parallel downloads but can be tuned via --max-concurrent-downloads for network optimization
  • Output flexibility ranges from interactive progress bars to machine-readable JSON through the --format flag
  • Programmatic access is available through the ContainerAPIClient Swift module, exposing the same pull logic used by the CLI
  • Registry compatibility supports standard OCI registries with automatic TLS negotiation and authentication handling

Frequently Asked Questions

How does platform resolution work when pulling images?

The runtime evaluates platform selectors in strict order: first checking the --platform flag, then separate --os and --arch flags, then the CONTAINER_DEFAULT_PLATFORM environment variable, and finally defaulting to the host's native platform. This logic resides in DefaultPlatform.resolve within the Container API Service.

Can I pull images from private registries with authentication?

Yes, the runtime supports authenticated registry connections. The ContainerAPIClient negotiates TLS and prepares authenticated HTTP clients automatically when credentials are configured. The scheme can be forced to https for secure private registries or set to auto for protocol detection.

How do I limit or increase download concurrency?

Use the --max-concurrent-downloads flag followed by an integer. The default value is 3 parallel downloads, but you can increase this for high-bandwidth connections or decrease it to reduce network impact on shared systems.

What output formats are supported for pull results?

By default, the CLI displays a tabular summary of pulled layers. You can suppress output with --quiet (showing only the image name) or use --format to render results as JSON, YAML, or TOML for machine parsing. Progress indicators can be customized via --progress using styles like ansi, plain, or color.

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 →