# How to Log In and Out of OCI Registries Using Container Registry Commands

> Log in and out of OCI registries with container registry commands. Securely store credentials in your macOS keychain for easy access.

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

---

**Use `container registry login <SERVER>` to authenticate with OCI-compatible registries and store credentials in the macOS keychain, and `container registry logout <SERVER>` to remove them.**

The open-source `container` tool from Apple provides native support for interacting with OCI-compliant container registries on macOS. When you need to push or pull images from private registries, you must first authenticate using the built-in registry commands that securely manage credentials via the platform keychain.

## Logging In to an OCI Registry

The `container registry login` command, implemented in [`Sources/ContainerCommands/Registry/RegistryLogin.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Registry/RegistryLogin.swift), handles the complete authentication lifecycle from credential collection to secure storage.

### Command Syntax and Options

The command accepts a server hostname as a positional argument and several optional flags:

- `--username`: Pre-specify the registry username
- `--password-stdin`: Read the password from standard input for CI/CD automation
- `--scheme`: Set the protocol to `http`, `https`, or `auto` (defined in `Flags.Registry`)

### Authentication Flow Implementation

According to the source code in [`RegistryLogin.swift`](https://github.com/apple/container/blob/main/RegistryLogin.swift), the login process follows these steps:

1. **Option Parsing**: Validates the server argument and optional flags.
2. **Credential Collection**: If `--password-stdin` is provided, reads from `stdin`. Otherwise, prompts via `KeychainHelper.userPrompt` and `KeychainHelper.passwordPrompt` for interactive input.
3. **URL Resolution**: Normalizes the hostname using `Reference.resolveDomain` and constructs the registry URL using the scheme from `Flags.Registry.scheme`.
4. **Credential Verification**: Creates a `RegistryClient` with `BasicAuthentication` and calls `ping()` to verify the credentials against the remote registry.
5. **Secure Storage**: On success, stores credentials in the macOS keychain under `Constants.keychainID`.
6. **Confirmation**: Outputs "Login succeeded" via the logging infrastructure.

## Logging Out of an OCI Registry

The `container registry logout` command, defined in [`Sources/ContainerCommands/Registry/RegistryLogout.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Registry/RegistryLogout.swift), removes stored credentials without contacting the remote server.

### How Logout Works

The logout implementation performs two primary operations:

1. **Domain Normalization**: Resolves the hostname using `Reference.resolveDomain` to match the stored keychain entry.
2. **Keychain Deletion**: Invokes `KeychainHelper.delete(hostname:)` to remove the credentials locally. This operation does not make network calls to invalidate sessions on the registry server.

## Practical Code Examples

### Interactive Login

For manual authentication, run the command without credentials to trigger interactive prompts:

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

```

The CLI will prompt for username (if `--username` is omitted) and password via the system keychain helper.

### Non-Interactive Login (CI/CD Pipelines)

For automation scripts, pass the username via flag and pipe the password:

```bash
printf 's3cr3tP@ss' | container registry login \
    --username myuser \
    --password-stdin \
    myregistry.example.com

```

### Removing Credentials

To delete stored authentication:

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

```

This immediately removes the entry from the macOS keychain.

## Summary

- **`container registry login`** authenticates to OCI registries and stores credentials securely in the macOS keychain via [`RegistryLogin.swift`](https://github.com/apple/container/blob/main/RegistryLogin.swift).
- **`container registry logout`** removes local credentials via [`RegistryLogout.swift`](https://github.com/apple/container/blob/main/RegistryLogout.swift) without network overhead.
- Use `--password-stdin` for secure automation in CI environments.
- Credentials are verified via `RegistryClient.ping()` before storage.

## Frequently Asked Questions

### Where are credentials stored when using `container registry login`?

Credentials are stored in the macOS keychain (or platform-specific equivalent) under a domain-specific identifier defined by `Constants.keychainID`, as implemented in [`Sources/ContainerPersistence/KeychainHelper.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/KeychainHelper.swift).

### Does `container registry logout` invalidate sessions on the registry server?

No. The logout command only removes credentials locally from the keychain using `KeychainHelper.delete(hostname:)` and does not contact the remote registry to invalidate active sessions.

### Can I use HTTP instead of HTTPS for local registries?

Yes. Use the `--scheme` flag (defined in `Flags.Registry`) to specify `http`, `https`, or `auto` when running `container registry login`.

### How does the CLI verify credentials before storing them?

The [`RegistryLogin.swift`](https://github.com/apple/container/blob/main/RegistryLogin.swift) implementation creates a `RegistryClient` with `BasicAuthentication` and calls the `ping()` method to verify credentials against the registry before persisting them to the keychain.