Documentation

Mirror Docker Hub official images

Docker Hub stores its official images under the library namespace: ubuntu is library/ubuntu. A client pulling through a peryx route sends the name a user typed, so docker pull peryx.internal:4433/hub/ubuntu reaches peryx as ubuntu, and Hub answers 401 for a repository by that name. [index.settings].library_prefix rewrites the upstream request.

Cache Docker Hub

# peryx.toml
[[index]]
name = "hub"
route = "hub"
ecosystem = "oci"

[[index.upstream]]
name = "primary"
url = "https://registry-1.docker.io"

[index.settings]
library_prefix = "auto" # the default; shown here for clarity

auto prefixes a single-segment name with library/ when the upstream host is Docker Hub, which is what this index proxies. Pull short names and names with a namespace through the same route:

docker pull peryx.internal:4433/hub/ubuntu:24.04           # peryx asks Hub for library/ubuntu
docker pull peryx.internal:4433/hub/library/nginx:latest   # passed through as spelled
docker pull peryx.internal:4433/hub/grafana/grafana:latest # a user repository, passed through

The rewrite reaches Hub only. peryx caches, tags, lists, and serves the image under hub/ubuntu, so a pipeline that names peryx.internal:4433/hub/ubuntu:24.04 keeps naming it that.

Pre-seed official images offline

peryx mirror pulls through the same rule, so a short name works there as well and lands in the store under that name:

peryx mirror sync hub --config peryx.toml --option 'images=["ubuntu:24.04","nginx:1.27"]'

Follow up with peryx mirror verify to confirm every manifest and blob is on disk before a run with the network off; see serve images air-gapped.

Override library_prefix

Use auto for Docker Hub and other upstreams. It rewrites only when the upstream host identifies Docker Hub. Set an explicit value for the following cases.

Set true when the upstream is a Hub-compatible mirror on a different host, so auto cannot recognize it. A pull-through mirror of Hub, or a corporate registry that reproduces Hub's namespace layout, wants short names resolved the way Hub resolves them:

[[index]]
name = "hub-mirror"
route = "hub"
ecosystem = "oci"

[[index.upstream]]
name = "primary"
url = "https://hub-mirror.internal"

[index.settings]
library_prefix = true

Set false when the upstream is Docker Hub but you want the name passed through verbatim: an index that only ever serves names with a namespace, or a debugging session where you need to see the client's exact request. With false, a pull of hub/ubuntu asks Hub for ubuntu and gets Hub's 401.

Registry-mirror mode needs neither. When the Docker daemon lists peryx under registry-mirrors, it resolves ubuntu to library/ubuntu before it calls the mirror, and a mirror index carries an empty route, so the full name arrives. See cache images for CI.

Troubleshoot failed pulls

An upstream 401 surfaces as a 401 with the UNAUTHORIZED code and a message naming the upstream, rather than as a missing manifest. On a Hub proxy, the repository name reached Hub without anonymous access. Check that library_prefix is not false, and that a user repository is spelled with its namespace. On a private upstream it points at the index's credentials. See Docker Hub names and upstream auth.

On this page