How Container Registry Connection Schemes Work in Apple’s Container Tool: HTTP, HTTPS, and Auto-Detection
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). This file declares a Sendable enum that represents the three possible transport protocols:
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, and172.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) within the Flags.Registry structure:
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) (around line 73), the login command resolves the scheme before authenticating:
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) (line 63) uses the same mechanism to configure the upload client:
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) (line 75) instantiates the scheme before fetching layers:
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:
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:
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:
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:
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
RequestSchemeenum inRequestScheme.swiftdefineshttp,https, andautoas valid container registry connection schemes. automode automatically selectshttpfor internal hosts (localhost, private IPs, internal DNS domains) andhttpsfor external endpoints.- The
Flags.Registrystruct exposes--schemeto the CLI, defaulting to"auto"for safe out-of-the-box behavior. - Commands including
registry login,image push, andimage pullresolve the scheme viaschemeFor(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 (enum and auto-detection), while the CLI interface is defined in Sources/Services/ContainerAPIService/Client/Flags.swift. Consumption occurs in Sources/ContainerCommands/Registry/RegistryLogin.swift, Sources/ContainerCommands/Image/ImagePush.swift, and 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.
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 →