# How Container Registry Connection Schemes Work in Apple’s Container Tool: HTTP, HTTPS, and Auto-Detection

> Learn how Apple's container CLI uses HTTP HTTPS and auto detection for registry connections. Understand private vs public endpoint schemes.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: deep-dive
- Published: 2026-07-09

---

**Apple’s `container` CLI uses a `RequestScheme` enum with `http`, `https`, and `auto` options to determine whether to use plain HTTP or TLS when connecting to OCI registries, automatically detecting private hosts to use HTTP while defaulting to HTTPS for public endpoints.**

The `container` command-line tool from Apple provides a Swift-native interface for interacting with OCI-compatible registries. When pushing or pulling images, the tool must decide whether to communicate over plain HTTP or encrypted HTTPS based on the target registry's location. This decision is governed by a configurable **container registry connection scheme** system that balances security with flexibility for private development environments.

## Understanding `RequestScheme`: The Core Enum for Container Registry Connection Schemes

The canonical definition of connection schemes resides in [[`Sources/Services/ContainerAPIService/Client/RequestScheme.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/RequestScheme.swift)](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/RequestScheme.swift). This file declares a `Sendable` enum that represents the three possible transport protocols:

```swift
public enum RequestScheme: String, Sendable {
    case http  = "http"
    case https = "https"
    case auto  = "auto"          // default for the CLI
}

```

Initialization via `RequestScheme(_:)` validates the raw string and throws an error if an unsupported value is supplied. The `auto` case implements intelligent protocol selection based on the target host’s network characteristics.

### Auto-Detection Logic for Internal Hosts

When `auto` is selected, the enum invokes `schemeFor(host:internalDnsDomain:)` to resolve the final transport protocol. This method delegates to `isInternalHost(host:internalDnsDomain:)`, which identifies private infrastructure by checking:

- The hostname `localhost`
- IPv4 CIDR ranges `10/8`, `127/8`, `192.168/16`, and `172.16/12`
- Hostnames ending with the configured internal DNS domain

If the host matches any internal criteria, the scheme resolves to **`http`**; otherwise, it falls back to **`https`**. This ensures that development registries running on private networks avoid TLS overhead and certificate errors, while public registries receive encrypted connections.

## Configuring Container Registry Connection Schemes via CLI Flags

User-facing configuration is defined in [[`Sources/Services/ContainerAPIService/Client/Flags.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Flags.swift)](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Flags.swift) within the `Flags.Registry` structure:

```swift
public struct Registry: ParsableArguments {
    @Option(help: "Scheme to use when connecting to the container registry. One of (http, https, auto)")
    public var scheme: String = "auto"
}

```

Because `Flags.Registry` is embedded in the global `Flags` hierarchy, commands that interact with registries automatically inherit the `--scheme` option. The default value of `"auto"` applies the intelligent detection logic described above, while explicit values of `"http"` or `"https"` override the heuristic and force the specified protocol regardless of host location.

## How Container Registry Connection Schemes Are Applied in Commands

The scheme selection flows through three primary commands, each following an identical pattern: construct a `RequestScheme` from the CLI flag, then apply `schemeFor(host:internalDnsDomain:)` to determine the final protocol.

### Registry Login

In [[`Sources/ContainerCommands/Registry/RegistryLogin.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Registry/RegistryLogin.swift)](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Registry/RegistryLogin.swift) (around line 73), the login command resolves the scheme before authenticating:

```swift
let scheme = try RequestScheme(registry.scheme)
                .schemeFor(host: server, internalDnsDomain: containerSystemConfig.dns.domain)

```

### Image Push

The push command in [[`Sources/ContainerCommands/Image/ImagePush.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Image/ImagePush.swift)](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Image/ImagePush.swift) (line 63) uses the same mechanism to configure the upload client:

```swift
let scheme = try RequestScheme(registry.scheme)

```

### Image Pull

Similarly, [[`Sources/ContainerCommands/Image/ImagePull.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Image/ImagePull.swift)](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Image/ImagePull.swift) (line 75) instantiates the scheme before fetching layers:

```swift
let scheme = try RequestScheme(registry.scheme)

```

In all three cases, the resulting scheme configures the underlying HTTP client to use either plain HTTP or TLS for the registry request.

## Practical Examples: Setting Container Registry Connection Schemes

### Default Auto Behavior for Public Registries

When pulling from Docker Hub or other public endpoints, omit the flag to automatically use HTTPS:

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

```

Because `docker.io` resolves to a public IP, the `auto` logic selects `https`.

### Accessing Private Registries Without TLS

For registries running on private IP ranges, the tool automatically uses HTTP:

```bash
container image pull 10.0.0.5:5000/myapp:latest

```

The host `10.0.0.5` falls within the `10/8` CIDR range, triggering the `http` scheme without manual configuration.

### Forcing HTTPS on Private Hosts

To override auto-detection and require TLS for a private registry:

```bash
container image push --scheme https registry.local/myapp:dev

```

The `--scheme https` flag bypasses the internal-host check and encrypts the connection.

### Programmatic Usage in Swift

Developers integrating the library directly can replicate the CLI logic:

```swift
import ContainerAPI

let registryFlags = Flags.Registry(scheme: "auto")
let baseScheme = try RequestScheme(registryFlags.scheme)
let finalScheme = try baseScheme.schemeFor(
    host: "registry.local", 
    internalDnsDomain: nil
)
// finalScheme resolves to .http for private hosts, .https otherwise

```

This pattern mirrors the command-line behavior, allowing programmatic control over container registry connection schemes.

## Summary

- The **`RequestScheme`** enum in [`RequestScheme.swift`](https://github.com/apple/container/blob/main/RequestScheme.swift) defines `http`, `https`, and `auto` as valid container registry connection schemes.
- **`auto`** mode automatically selects `http` for internal hosts (localhost, private IPs, internal DNS domains) and `https` for external endpoints.
- The **`Flags.Registry`** struct exposes `--scheme` to the CLI, defaulting to `"auto"` for safe out-of-the-box behavior.
- Commands including **`registry login`**, **`image push`**, and **`image pull`** resolve the scheme via `schemeFor(host:internalDnsDomain:)` before establishing connections.
- Explicit scheme flags override auto-detection, enabling TLS for private registries or plain HTTP for public testing endpoints when required.

## Frequently Asked Questions

### What is the default container registry connection scheme in Apple’s container tool?

The default scheme is **`auto`**, as defined in `Flags.Registry`. When set to `auto`, the tool examines the target host and uses `http` for internal addresses (localhost, private IP ranges like `10.x.x.x`, or hosts matching the internal DNS domain) and `https` for all other public endpoints.

### How do I force HTTPS for a registry running on a private IP address?

Use the `--scheme https` flag with any registry command. For example: `container image pull --scheme https 192.168.1.10:5000/myimage`. This overrides the automatic `http` selection that normally occurs for private IP ranges.

### Which source files handle the logic for registry connection schemes?

The core logic lives in **[`Sources/Services/ContainerAPIService/Client/RequestScheme.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/RequestScheme.swift)** (enum and auto-detection), while the CLI interface is defined in **[`Sources/Services/ContainerAPIService/Client/Flags.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Flags.swift)**. Consumption occurs in **[`Sources/ContainerCommands/Registry/RegistryLogin.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Registry/RegistryLogin.swift)**, **[`Sources/ContainerCommands/Image/ImagePush.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Image/ImagePush.swift)**, and **[`Sources/ContainerCommands/Image/ImagePull.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Image/ImagePull.swift)**.

### Can I use HTTP for a public registry in the container tool?

Yes, by explicitly setting `--scheme http` when running commands like `image pull` or `image push`. However, this is generally discouraged for public registries as it transmits data unencrypted. The tool defaults to HTTPS for public hosts to ensure secure communication.