# How Container Authenticates with Container Registries: Basic Auth and Keychain Storage

> Learn how container authenticates with registries using basic auth and secure macOS Keychain storage. Understand the credential verification process.

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

---

**Container authenticates with container registries using a basic-auth workflow that verifies credentials via a ping request before storing them securely in the macOS Keychain under the domain `com.apple.container.registry`.**

The `apple/container` command-line tool manages OCI-compliant container images on macOS, requiring secure authentication with remote registries. When you configure container authentication with container registries, the tool implements a streamlined flow that validates credentials before persisting them, enabling automatic reuse across subsequent pull, push, and list operations.

## The Authentication Flow

### Credential Gathering and Initial Verification

Authentication begins in [`Sources/ContainerCommands/Registry/RegistryLogin.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Registry/RegistryLogin.swift), where the `login` subcommand collects username and password inputs either interactively or via the `--password-stdin` flag. These credentials are wrapped in a **BasicAuthentication** instance and passed to a **RegistryClient** along with the configured scheme (http/https) and optional port. The client performs a ping request to verify both network connectivity and authentication validity (lines 49-87).

### Secure Storage in macOS Keychain

Upon successful verification, [`RegistryLogin.swift`](https://github.com/apple/container/blob/main/RegistryLogin.swift) invokes `KeychainHelper.save(...)` to persist the credentials (lines 90-97). The storage uses the domain identifier defined in [`Sources/Services/ContainerAPIService/Client/Constants.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Constants.swift). Subsequent registry operations retrieve these credentials automatically via `KeychainHelper.lookup(hostname:)`, attaching them to every HTTP request without prompting the user.

### Automatic Retry Handling

The **RegistryClient** handles all HTTP communication with the registry, applying the stored **BasicAuthentication** credentials to each request. It automatically retries on server-side 5xx errors according to the configured retry policy, ensuring robust communication even during temporary registry unavailability.

## Removing Stored Credentials

To delete stored credentials, the `logout` subcommand implemented in [`Sources/ContainerCommands/Registry/RegistryLogout.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Registry/RegistryLogout.swift) removes the Keychain entry. It calls `KeychainHelper.delete(...)` to eliminate the stored authentication data for the specific registry hostname (lines 34-41).

## Practical Code Examples

### Interactive Login

Prompt for credentials securely in the terminal:

```bash
container registry login myregistry.example.com

```

### Script-Based Login with stdin

Provide credentials via standard input for automation or CI/CD pipelines:

```bash
echo "mySecretPassword" | container registry login \
    --username myuser --password-stdin myregistry.example.com

```

### Automatic Credential Usage

After login, subsequent commands automatically retrieve credentials from the Keychain:

```bash
container image pull myregistry.example.com/myimage:latest
container image push myregistry.example.com/myimage:v1.0

```

### Logging Out

Remove stored credentials for a specific registry:

```bash
container registry logout myregistry.example.com

```

## Summary

- **BasicAuthentication** objects wrap username/password credentials gathered by [`RegistryLogin.swift`](https://github.com/apple/container/blob/main/RegistryLogin.swift).
- Credentials are verified via a **ping request** before being stored in the **macOS Keychain** under `com.apple.container.registry`.
- **RegistryClient** retrieves credentials automatically for subsequent operations and handles **5xx retry logic**.
- **RegistryLogout.swift** permanently removes credentials using `KeychainHelper.delete(...)`.

## Frequently Asked Questions

### Where does Container store registry credentials?

Container stores credentials in the macOS Keychain under the service identifier `com.apple.container.registry` using `KeychainHelper.save(...)`. This provides encrypted, system-level storage that persists across reboots and integrates with macOS security policies.

### How does Container verify credentials before storing them?

Before persisting credentials to the Keychain, [`RegistryLogin.swift`](https://github.com/apple/container/blob/main/RegistryLogin.swift) instantiates a `RegistryClient` to perform a ping request against the registry. This validates both network connectivity and authentication credentials, ensuring only valid credentials are stored under the keychain domain.

### Can I use Container in CI/CD scripts without interactive prompts?

Yes. Use the `--password-stdin` flag to pipe passwords securely via standard input. For example: `echo "$PASSWORD" | container registry login --username "$USER" --password-stdin registry.example.com`. This avoids interactive prompts and keeps credentials out of shell history.

### How does Container handle registry communication errors?

The `RegistryClient` automatically retries requests when encountering server-side 5xx errors, respecting the configured retry policy. This ensures robust communication during temporary registry outages or high-load periods.