Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,60 @@ Or pull images directly:
docker pull localhost:8080/library/nginx:latest
```

#### containerd (Kubernetes, k3s, nerdctl)

containerd mirrors send the original registry host in an `ns` query
parameter, so one mirror entry can serve Docker Hub and the registries
configured in `upstream.oci` whose URL has no path. Point containerd's CRI
plugin at a hosts directory in `/etc/containerd/config.toml` and restart
containerd. For containerd 2.x:

```toml
version = 3

[plugins."io.containerd.cri.v1.images".registry]
config_path = "/etc/containerd/certs.d"
```

For containerd 1.x:

```toml
version = 2

[plugins."io.containerd.grpc.v1.cri".registry]
config_path = "/etc/containerd/certs.d"
```

Then create `/etc/containerd/certs.d/_default/hosts.toml`:

```toml
[host."http://proxy.example.com:8080"]
capabilities = ["pull", "resolve"]
```

To check that CRI picked up the directory, confirm the setting containerd
runs with and pull through CRI (on k3s use `k3s crictl`):

```bash
containerd config dump | grep config_path
crictl pull docker.io/library/nginx:latest
```

The proxy logs a `container manifest request` line for the pull and, when
`access_log.path` is set, an access-log entry. `ctr images pull --hosts-dir`
is no substitute for this check: it reads the directory itself and succeeds
even while CRI still has no `config_path`.

`docker.io` and the host of `upstream.oci_default` use the default registry;
the host of each `upstream.oci` URL uses that named registry. Pulls for any
other registry get `404 NAME_UNKNOWN`, and containerd falls back to the
registry itself. Existing per-registry `hosts.toml` files that point at
`/v2/upstream/{name}` with `override_path = true` keep working. See [docs/configuration.md](docs/configuration.md) for how
hosts are matched and which entry wins when two share a host. k3s generates
the hosts directory itself from `/etc/rancher/k3s/registries.yaml`; `mirrors:
{"*": {endpoint: ["http://proxy.example.com:8080"]}}` produces the same
`_default` entry.

### Helm

Configure each HTTP chart repository with a name, then add the matching proxy
Expand Down
20 changes: 20 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,26 @@ mise section in the README for the client-side `url_replacements`.
while `upstream.oci` selects named registries through the `upstream/{name}/`
repository prefix. For example, `oci://proxy.example.com/upstream/ghcr/owner/chart`
uses the `ghcr` registry with `owner/chart` as its repository.

containerd mirror requests carry the original registry host in an `ns` query
parameter (see the containerd section in the README). The proxy only looks the
host up and never connects to it: `docker.io`, `index.docker.io`,
`registry-1.docker.io` and the host of `upstream.oci_default` select the default
registry, and the host of each `upstream.oci` URL selects that named registry.
Hosts are compared case-insensitively. The scheme's default port (443 for
`https`, 80 for `http`) may be spelled out or left out in the image reference;
any other port must match exactly, so `https://registry.example:80` and
`https://registry.example` are two different registries. An
unknown host returns `404 NAME_UNKNOWN`, so containerd falls back to its next
host. Registry URLs with a path (for example an Artifactory repository path)
are not reachable through `ns`, only through `upstream/{name}/`. When two
entries share a host, the proxy logs a warning at startup; the default registry
wins, otherwise the alphabetically first name. Pulls through `ns`,
`upstream/{name}/` and unprefixed requests share the same cache entries.
Requests that combine the `upstream/{name}/` prefix with `ns`, as per-registry
containerd mirrors with `override_path = true` send them, are accepted when
`ns` names that upstream's host, also for upstreams whose URL has a path, and
rejected otherwise.
When the proxy uses plain HTTP (for example `localhost:8080`), pass
`--plain-http` to Helm OCI commands.

Expand Down
Loading
Loading