> This page is for version 0.7.0.
> For other versions, use one of these documentation indexes:
> - Main (default): https://docs.nvidia.com/nemo/gym/main/llms.txt
> - 0.7.0: https://docs.nvidia.com/nemo/gym/v0.7.0/llms.txt
> - 0.6.0: https://docs.nvidia.com/nemo/gym/v0.6.0/llms.txt
> - 0.5.1: https://docs.nvidia.com/nemo/gym/v0.5.1/llms.txt
> - 0.5.0: https://docs.nvidia.com/nemo/gym/v0.5.0/llms.txt
> - 0.4.0: https://docs.nvidia.com/nemo/gym/v0.4.0/llms.txt
> - 0.3.0: https://docs.nvidia.com/nemo/gym/v0.3.0/llms.txt
> - 0.2.1: https://docs.nvidia.com/nemo/gym/v0.2.1/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/nemo/gym/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/nemo/gym/_mcp/server.

# nemo_gym.tasks.harbor.registry

Read an image's configuration from its OCI registry.

Parses Docker-style references with Docker Hub defaults, selects the platform's manifest from
an index, follows the bearer token challenge, drops authorization across redirects, retries
transient failures and returns the configuration keys the records keep, pinned to the digest
of the manifest the reference named. Nothing here knows about tasks or Compose. The module
keeps the record key list, the platform constants and ImageConfigError, which the rest of the
package imports from here.

## Module Contents

### Classes

| Name                                                                   | Description                                                                                     |
| ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| [`ImageConfigError`](#nemo_gym-tasks-harbor-registry-ImageConfigError) | An image reference could not be resolved to a linux/amd64 configuration.                        |
| [`ImageRef`](#nemo_gym-tasks-harbor-registry-ImageRef)                 | A parsed image reference: `[registry/]repository[:tag][@digest]`.                               |
| [`RegistryClient`](#nemo_gym-tasks-harbor-registry-RegistryClient)     | Read manifests and configuration blobs over the OCI distribution API with the standard library. |
| [`_RedirectHandler`](#nemo_gym-tasks-harbor-registry-_RedirectHandler) | Follow a registry redirect without carrying the registry's token to another host.               |

### Functions

| Name                                                                 | Description                                                             |
| -------------------------------------------------------------------- | ----------------------------------------------------------------------- |
| [`parse_image_ref`](#nemo_gym-tasks-harbor-registry-parse_image_ref) | Split an image reference the way Docker does, defaulting to Docker Hub. |

### Data

[`DOCKER_HUB_REGISTRY`](#nemo_gym-tasks-harbor-registry-DOCKER_HUB_REGISTRY)

[`INDEX_MEDIA_TYPES`](#nemo_gym-tasks-harbor-registry-INDEX_MEDIA_TYPES)

[`MANIFEST_ACCEPT`](#nemo_gym-tasks-harbor-registry-MANIFEST_ACCEPT)

[`PLATFORM`](#nemo_gym-tasks-harbor-registry-PLATFORM)

[`RECORDED_CONFIG_KEYS`](#nemo_gym-tasks-harbor-registry-RECORDED_CONFIG_KEYS)

### API

```python
class nemo_gym.tasks.harbor.registry.ImageConfigError()
```

**Bases:** `RuntimeError`

An image reference could not be resolved to a linux/amd64 configuration.

```python
class nemo_gym.tasks.harbor.registry.ImageRef(
    registry: str,
    repository: str,
    tag: str | None,
    digest: str | None
)
```

Dataclass

A parsed image reference: `[registry/]repository[:tag][@digest]`.

**`digest`** `str | None`

---

**`manifest_ref`** `str`

---

**`pinned_repository`** `str`

The repository a digest pin is written against: as the registry names it, host included off Docker Hub.

---

**`registry`** `str`

---

**`repository`** `str`

---

**`tag`** `str | None`

---

```python
class nemo_gym.tasks.harbor.registry.RegistryClient(
    credentials: dict[str, tuple[str, str]] | None = None,
    timeout_s: float = 60,
    retries: int = 3
)
```

Read manifests and configuration blobs over the OCI distribution API with the standard library.

`credentials` maps a registry host to `(username, password)` for private repositories;
public ones use the anonymous token the registry hands out.

**`_opener`** `= urllib.request.build_opener(_RedirectHandler())`

---

**`_tokens`** `dict[tuple[str, str], str] = {}`

---

**`credentials`** `= credentials or {}`

---

```python
nemo_gym.tasks.harbor.registry.RegistryClient._get(
    ref: nemo_gym.tasks.harbor.registry.ImageRef,
    path: str,
    accept: str
) -> tuple[bytes, dict[str, str]]
```

```python
nemo_gym.tasks.harbor.registry.RegistryClient._manifest(
    ref: nemo_gym.tasks.harbor.registry.ImageRef,
    manifest_ref: str
) -> tuple[dict[str, typing.Any], str]
```

```python
nemo_gym.tasks.harbor.registry.RegistryClient._open(
    url: str,
    headers: dict[str, str]
) -> tuple[bytes, dict[str, str]]
```

One GET; connection-level failures (not HTTP errors) are retried with a short backoff.

```python
nemo_gym.tasks.harbor.registry.RegistryClient._select_platform(
    ref: nemo_gym.tasks.harbor.registry.ImageRef,
    index: dict[str, typing.Any]
) -> str
```

```python
nemo_gym.tasks.harbor.registry.RegistryClient._token(
    ref: nemo_gym.tasks.harbor.registry.ImageRef,
    challenge: str
) -> str
```

```python
nemo_gym.tasks.harbor.registry.RegistryClient.image_config(
    reference: str
) -> dict[str, typing.Any]
```

One `compose-images.json` entry for `reference`.

```python
class nemo_gym.tasks.harbor.registry._RedirectHandler()
```

**Bases:** `HTTPRedirectHandler`

Follow a registry redirect without carrying the registry's token to another host.

Registries answer a blob request with a redirect to a storage host (Docker Hub, GHCR and ECR all
do). The OCI distribution spec says a client must not send its `Authorization` there, and the
default handler forwards every header, so the header is dropped whenever the host changes.

```python
nemo_gym.tasks.harbor.registry._RedirectHandler.redirect_request(
    req,
    fp,
    code,
    msg,
    headers,
    newurl
)
```

```python
nemo_gym.tasks.harbor.registry.parse_image_ref(
    reference: str
) -> nemo_gym.tasks.harbor.registry.ImageRef
```

Split an image reference the way Docker does, defaulting to Docker Hub.

```python
nemo_gym.tasks.harbor.registry.DOCKER_HUB_REGISTRY = 'registry-1.docker.io'
```

```python
nemo_gym.tasks.harbor.registry.INDEX_MEDIA_TYPES = {'application/vnd.oci.image.index.v1+json', 'application/vnd.docker.distribution...
```

```python
nemo_gym.tasks.harbor.registry.MANIFEST_ACCEPT = ', '.join(['application/vnd.oci.image.index.v1+json', 'application/vnd.oci.image...
```

```python
nemo_gym.tasks.harbor.registry.PLATFORM = ('linux', 'amd64')
```

```python
nemo_gym.tasks.harbor.registry.RECORDED_CONFIG_KEYS = ('Cmd', 'Entrypoint', 'Env', 'ExposedPorts', 'Healthcheck', 'Shell', 'User', 'Wo...
```