# Container Registry Authentication and Credential Storage in Apple's Container Tool

> Secure your container registry with Apple's container tool. Learn about secure credential storage in macOS Keychain and registry login logout and list commands.

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

---

**The `container` CLI stores registry credentials securely in the macOS Keychain under the identifier `com.apple.container.registry`, providing login, logout, and list commands via `RegistryLogin`, `RegistryLogout`, and `RegistryList`.**

The `apple/container` project provides a Swift-based container management solution that integrates deeply with macOS security primitives. Unlike tools that cache credentials in plain-text configuration files, this implementation leverages the system Keychain for **container registry authentication and credential storage**, ensuring secrets remain encrypted and access-controlled by the operating system.

## Keychain Integration and Security Domain

All credential operations are centralized through `KeychainHelper`, which abstracts macOS Keychain access using the repository-wide security domain defined in [`Sources/Services/ContainerAPIService/Client/Constants.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Constants.swift). At line 20, the constant `Constants.keychainID` is set to `"com.apple.container.registry"`, serving as the exclusive identifier for all stored entries. This design prevents credential leakage and ties authentication data to the user's system-level security policies.

The helper exposes three core methods for credential lifecycle management:
- `KeychainHelper.save(hostname:username:password:)` – Persists credentials after validation.
- `KeychainHelper.delete(hostname:)` – Removes entries during logout.
- `KeychainHelper.list()` – Retrieves all stored `RegistryInfo` objects for enumeration.

## Authentication Lifecycle Commands

### Logging In via RegistryLogin

The `container registry login` command is implemented in [`Sources/ContainerCommands/Registry/RegistryLogin.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Registry/RegistryLogin.swift) (lines 63-97). The workflow first constructs a `BasicAuthentication` object from the provided username and password (optionally supplied via the `--password-stdin` flag). It then validates connectivity by pinging the registry endpoint. Upon successful verification, the credentials are persisted using `KeychainHelper.save(hostname:username:password:)`.

```bash

# Log in to a registry (prompts for username/password or reads password from stdin)

container registry login myregistry.example.com \
    --username alice \
    --password-stdin < password.txt

```

### Logging Out via RegistryLogout

The `container registry logout` command, found in [`Sources/ContainerCommands/Registry/RegistryLogout.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Registry/RegistryLogout.swift) (lines 36-40), performs a straightforward deletion. It invokes `KeychainHelper.delete(hostname:)` to remove the specific entry associated with the provided registry host, ensuring no residual authentication data remains on the system.

```bash

# Log out (remove credentials)

container registry logout myregistry.example.com

```

### Listing Stored Credentials via RegistryList

To enumerate configured registries, the `registry list` command uses [`Sources/ContainerCommands/Registry/RegistryList.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Registry/RegistryList.swift) (lines 41-50). This command calls `KeychainHelper.list()` to fetch all entries, then maps each `RegistryInfo` instance to a `RegistryResource` object as defined in [`Sources/ContainerResource/Registry/RegistryResource.swift`](https://github.com/apple/container/blob/main/Sources/ContainerResource/Registry/RegistryResource.swift) (lines 20-52). Output is rendered as a formatted table by default, or as a simple hostname list when the `-q` (quiet) flag is specified.

```bash

# Show stored registry credentials

container registry list           # table view

container registry list -q       # quiet – only hostnames

```

## Runtime Credential Retrieval for Image Operations

When pulling or pushing images, the system retrieves stored credentials to construct a `RegistryClient`. In [`Sources/ContainerAPIService/Client/ClientImage.swift`](https://github.com/apple/container/blob/main/Sources/ContainerAPIService/Client/ClientImage.swift) (lines 62-71), the code resolves the connection scheme—either `http` or `https`—based on command-line flags such as `--scheme` and internal DNS domain checks. It then instantiates `BasicAuthentication` with the username and password recovered from the Keychain, passing this object to the `RegistryClient` initializer.

```swift
// Programmatic login handling (simplified)
let keychain = KeychainHelper(securityDomain: Constants.keychainID)

// Prompt user if needed
let username = try keychain.userPrompt(hostname: server)
let password = try keychain.passwordPrompt()

// Save credentials
try keychain.save(hostname: server, username: username, password: password)

// Later – retrieve for image pull
let stored = try keychain.list().first { $0.hostname == server }
let auth = BasicAuthentication(username: stored?.username ?? "", password: stored?.password ?? "")
let client = RegistryClient(host: server, scheme: "https", port: nil, authentication: auth)

```

## Key Source Files

The credential management subsystem spans the following critical paths:

- **[`Sources/ContainerCommands/Registry/RegistryLogin.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Registry/RegistryLogin.swift)** – Implements the login workflow and credential validation.
- **[`Sources/ContainerCommands/Registry/RegistryLogout.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Registry/RegistryLogout.swift)** – Handles secure credential deletion.
- **[`Sources/ContainerCommands/Registry/RegistryList.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Registry/RegistryList.swift)** – Provides enumeration and display logic.
- **[`Sources/ContainerResource/Registry/RegistryResource.swift`](https://github.com/apple/container/blob/main/Sources/ContainerResource/Registry/RegistryResource.swift)** – Defines the `RegistryResource` model for stored entries.
- **[`Sources/Services/ContainerAPIService/Client/Constants.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Constants.swift)** – Declares the `keychainID` constant.
- **[`Sources/ContainerAPIService/Client/ClientImage.swift`](https://github.com/apple/container/blob/main/Sources/ContainerAPIService/Client/ClientImage.swift)** – Orchestrates credential retrieval during image pull/push operations.

## Summary

- **Secure Storage**: Credentials are stored exclusively in the macOS Keychain under the identifier `"com.apple.container.registry"`, never in plain-text files.
- **Command Interface**: Users interact with credentials through `registry login`, `registry logout`, and `registry list` commands.
- **Validation Flow**: Login operations validate registry connectivity via ping before persisting secrets via `KeychainHelper.save(hostname:username:password:)`.
- **Runtime Usage**: Image operations retrieve credentials using `KeychainHelper.list()`, construct `BasicAuthentication` objects, and inject them into `RegistryClient` instances with configurable schemes (`http`/`https`).

## Frequently Asked Questions

### Where does the container CLI store registry credentials?

Credentials are stored in the macOS Keychain under the security domain identifier `"com.apple.container.registry"`, defined in [`Sources/Services/ContainerAPIService/Client/Constants.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Constants.swift). This ensures encryption at rest and aligns with system-wide access controls.

### How can I log in to a registry non-interactively?

Use the `--password-stdin` flag with `container registry login` to pipe the password via standard input. This avoids exposing secrets in shell history and is handled by the `RegistryLogin` implementation in [`Sources/ContainerCommands/Registry/RegistryLogin.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Registry/RegistryLogin.swift).

### What authentication method is used for registry operations?

The tool utilizes `BasicAuthentication` objects constructed from Keychain-stored username/password pairs. These are passed to `RegistryClient` during instantiation, as seen in the credential retrieval flow within [`ClientImage.swift`](https://github.com/apple/container/blob/main/ClientImage.swift).

### How do I configure the connection scheme for insecure registries?

Specify the `--scheme` flag (e.g., `--scheme http`) when executing commands. The `ClientImage` logic (lines 62-71) resolves the scheme based on this flag and internal DNS domain checks before initiating the connection.