# How to Save and Load Container Images as TAR Archives Using the Apple Container Tool

> Easily save and load container images as tar archives with the apple container CLI. Learn how to export and import OCI images efficiently without external dependencies.

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

---

**The `container` CLI provides `image save` and `image load` subcommands to export and import OCI images as tar archives, using XPC communication with the Container API service to stream data without external runtime dependencies.**

The `apple/container` repository provides a native Apple ecosystem implementation for managing OCI-compliant container images. When you need to transfer images between environments or create offline backups, you can save and load container images as tar archives using the built-in command-line interface and Swift API.

## Architecture of the Save and Load System

The export and import workflow operates through a distributed architecture involving command-line parsers, XPC clients, and a dedicated image service.

### CLI Entry Points

The user-facing commands are implemented in `Sources/ContainerCommands/Image/`:

- **ImageSave.swift** – Handles the `container image save` command, gathering image references, optional platform selectors, and output paths
- **ImageLoad.swift** – Implements `container image load`, accepting tar file paths or stdin input with an optional `--force` flag for invalid archives

Both commands utilize **ArgumentParser** with `@Option`, `@Flag`, and `@OptionGroup` decorators to expose CLI parameters.

### XPC Client Communication

The commands delegate to [`ClientImage.swift`](https://github.com/apple/container/blob/main/ClientImage.swift) (`Sources/Services/ContainerAPIService/Client/`), which builds an XPC client via `newXPCClient` to communicate with the `container-core-images` service (`ClientImage.serviceIdentifier`). Requests are encoded as `XPCMessage` objects and dispatched through `XPCClient.send`.

### Server-Side Archive Processing

The actual tar creation and extraction occurs in [`ImagesService.swift`](https://github.com/apple/container/blob/main/ImagesService.swift) (`Sources/Services/ContainerImagesService/Server/`):

- For **save** operations, the service iterates over requested references, resolves OCI descriptors, streams layer blobs into a temporary directory, then tars the directory
- For **load** operations, the service receives the tar file, validates members (rejecting invalid ones unless `--force` is set), and unpacks images into the content store

## Saving Container Images as TAR Archives

To export images to a portable archive format, use the `image save` command.

### Saving to a File

Specify the output path with the `--output` flag:

```bash
container image save alpine:latest --output alpine.tar

```

If you omit `--output`, the archive streams to stdout, enabling compression or direct piping:

```bash
container image save alpine:latest | gzip > alpine.tar.gz

```

### Platform-Specific Exports

The `ImageSave` command supports platform selection through `DefaultPlatform.resolve` (defined in [`DefaultPlatform.swift`](https://github.com/apple/container/blob/main/DefaultPlatform.swift)). Use `--os`, `--arch`, or `--platform` flags, or set the `CONTAINER_DEFAULT_PLATFORM` environment variable:

```bash
container image save alpine:latest --platform linux/amd64 --output alpine-amd64.tar

```

## Loading Container Images from TAR Archives

Import previously saved archives using the `image load` command.

### Loading from a File

Specify the input path with the `--input` flag:

```bash
container image load --input alpine.tar

```

### Loading from Standard Input

When `--input` is omitted, the command reads from stdin:

```bash
cat alpine.tar | container image load

```

### Handling Invalid Archives

Use the `--force` flag to load archives containing invalid members that would otherwise be rejected:

```bash
container image load --input corrupted.tar --force

```

After successful loading, the command prints loaded image references to stdout, making it easy to script subsequent operations.

## Direct Piping Between Save and Load

You can pipe the output of `save` directly into `load` to transfer images without touching the filesystem:

```bash
container image save busybox:latest | container image load

```

This streams the tar archive through a temporary file in `FileManager.default.temporaryDirectory` while the `ProgressBar` (from [`ProgressBar.swift`](https://github.com/apple/container/blob/main/ProgressBar.swift)) provides visual feedback for both operations.

## Programmatic API Usage

The Swift API exposed in [`ClientImage.swift`](https://github.com/apple/container/blob/main/ClientImage.swift) allows programmatic access to save and load functionality.

### Saving Images Programmatically

```swift
import ContainerAPIClient
import Foundation

let refs = ["alpine:latest"]
let outPath = "/tmp/alpine.tar"

try await ClientImage.save(
    references: refs,
    out: outPath,
    platform: nil,               // Uses current platform
    containerSystemConfig: .default
)

```

### Loading Images Programmatically

```swift
let result = try await ClientImage.load(
    from: outPath,
    force: false
)

for img in result.images {
    print("Loaded image:", img.reference)
}

```

The `ImageLoadResult` struct (defined in [`ImageLoadResult.swift`](https://github.com/apple/container/blob/main/ImageLoadResult.swift)) contains the list of loaded images and any rejected members.

## Implementation Details

### Progress Reporting

Both commands instantiate a `ProgressBar` (configured with `ProgressConfig`) to display task progress while streaming archives to and from the server.

### Temporary File Handling

When reading from stdin (`ImageLoad`) or writing to stdout (`ImageSave`), the system creates temporary tar files in `FileManager.default.temporaryDirectory`. Data is processed in 4 KB chunks using `FileHandle` operations.

### Error Handling

Errors are wrapped in `ContainerizationError` and surfaced via the CLI's `log.error` mechanism and `Application.exit`, providing consistent error reporting across the tool.

## Summary

- Use `container image save` to export OCI images as tar archives to files or stdout
- Use `container image load` to import archives from files or stdin into the content store
- Both commands support pipeline operations for efficient image transfer without intermediate files
- The Swift API through `ClientImage.save()` and `ClientImage.load()` provides programmatic access for automation
- Server-side processing in [`ImagesService.swift`](https://github.com/apple/container/blob/main/ImagesService.swift) handles the actual archive creation and extraction, operating entirely within the Apple container subsystem without external runtimes

## Frequently Asked Questions

### Can I save multiple images to a single tar archive?

Yes. The `ImageSave` command accepts multiple image references as arguments and bundles them into a single archive. The server-side implementation in [`ImagesService.swift`](https://github.com/apple/container/blob/main/ImagesService.swift) iterates over all references and includes their resolved OCI descriptors and layer blobs in the output tar.

### How does the tool handle platform-specific images?

The `DefaultPlatform.resolve` method in [`DefaultPlatform.swift`](https://github.com/apple/container/blob/main/DefaultPlatform.swift) processes `--os`, `--arch`, and `--platform` arguments, falling back to the `CONTAINER_DEFAULT_PLATFORM` environment variable if set. This allows you to export images for specific architectures even when running on a different host platform.

### What happens if a tar archive contains invalid members during load?

By default, the load operation validates archive members and rejects invalid ones. However, you can use the `--force` flag (handled in [`ImageLoad.swift`](https://github.com/apple/container/blob/main/ImageLoad.swift)) to override this behavior and force the loading of archives containing invalid members. The `ImageLoadResult` will indicate which members were rejected even when forcing the load.

### Is external software required to create or extract the archives?

No. The `container` tool manages the entire OCI image lifecycle internally. The [`ImagesService.swift`](https://github.com/apple/container/blob/main/ImagesService.swift) implementation handles tar creation and extraction directly without invoking external container runtimes or command-line tools like `docker` or `tar`.