# Container Images

A container Registry proxy cache for users on the ZJU campus network.

## Service scope

This service is available only from the ZJU campus network and does not require authentication.

Only allowlisted images are served. The allowlist follows the public list of images provided by `m.daocloud.io`, which has completed ICP filing in China, in [DaoCloud public-image-mirror's allows.txt](https://github.com/DaoCloud/public-image-mirror/blob/main/allows.txt) to help ensure that served images are compliant and safe. If the image you need is not allowlisted, request it through an issue in [DaoCloud/public-image-mirror](https://github.com/DaoCloud/public-image-mirror) or [ZJUSCT/mirrors.zju.edu.cn](https://github.com/ZJUSCT/mirrors.zju.edu.cn).

The proxy currently covers these upstream registries:

| Registry | Proxy path prefix |
| --- | --- |
| Docker Hub | `registry.mirrors.zjusct.io/hub.docker.com/` |
| GitHub Container Registry | `registry.mirrors.zjusct.io/ghcr.io/` |
| Quay | `registry.mirrors.zjusct.io/quay.io/` |
| NVIDIA Container Registry | `registry.mirrors.zjusct.io/nvcr.io/` |
| Kubernetes Registry | `registry.mirrors.zjusct.io/registry.k8s.io/` |
| GitLab Container Registry | `registry.mirrors.zjusct.io/registry.gitlab.com/` |
| Amazon ECR Public Gallery | `registry.mirrors.zjusct.io/public.ecr.aws/` |
| Microsoft Artifact Registry | `registry.mirrors.zjusct.io/mcr.microsoft.com/` |
| Elastic Container Registry | `registry.mirrors.zjusct.io/docker.elastic.co/` |
| Google Container Registry | `registry.mirrors.zjusct.io/gcr.io/` |
| Legacy Kubernetes GCR | `registry.mirrors.zjusct.io/k8s.gcr.io/` |
| Google US Container Registry | `registry.mirrors.zjusct.io/us.gcr.io/` |
| LinuxServer.io | `registry.mirrors.zjusct.io/lscr.io/` |
| OSGeo Docker Registry | `registry.mirrors.zjusct.io/docker.osgeo.org/` |

Docker Hub aliases such as `docker.io` and `registry-1.docker.io` are also supported.

## Quick start

Put the complete original image name after `registry.mirrors.zjusct.io/`:

```console
docker pull registry.mirrors.zjusct.io/ghcr.io/owner/image:tag
docker pull registry.mirrors.zjusct.io/registry.k8s.io/pause:3.10
docker pull registry.mirrors.zjusct.io/quay.io/prometheus/prometheus:latest
```

The complete proxy name works in Docker, Podman, containerd, Kubernetes, Compose, and other OCI image tools:

```yaml
image: registry.mirrors.zjusct.io/hub.docker.com/library/redis:7
```

Docker Hub names often omit the registry hostname and the `library/` namespace for official images. Add both when using this proxy:

| Original name | Proxy name |
| --- | --- |
| `ubuntu:24.04` | `registry.mirrors.zjusct.io/hub.docker.com/library/ubuntu:24.04` |
| `library/nginx:stable` | `registry.mirrors.zjusct.io/hub.docker.com/library/nginx:stable` |
| `prom/prometheus:latest` | `registry.mirrors.zjusct.io/hub.docker.com/prom/prometheus:latest` |

Rule: add `hub.docker.com/` when the name has no registry hostname; add `library/` when it has one path component; then prepend `registry.mirrors.zjusct.io/`.

## Configure clients

For Docker Hub only, you can configure the client to keep original image names. The longer configurations are collapsed below.

<details>
<summary>Docker Engine / Docker Desktop</summary>

Merge this into `/etc/docker/daemon.json`; in Docker Desktop, use **Settings → Docker Engine**:

```json
{
  "registry-mirrors": ["https://docker.mirrors.zjusct.io"]
}
```

Restart Docker on Linux with systemd. Rootless Docker usually uses
`~/.config/docker/daemon.json` and `systemctl --user restart docker`.
This only proxies Docker Hub; use complete proxy names for other registries. Docker may fall back to a direct Docker Hub connection if the mirror fails.
</details>

<details>
<summary>Podman / Buildah / Skopeo</summary>

Save this as `/etc/containers/registries.conf.d/99-zju-mirrors.conf`; personal configuration can use `~/.config/containers/registries.conf.d/99-zju-mirrors.conf`:

```toml
[[registry]]
prefix = "docker.io"
location = "registry.mirrors.zjusct.io/hub.docker.com"

[[registry]]
prefix = "ghcr.io"
location = "registry.mirrors.zjusct.io/ghcr.io"

[[registry]]
prefix = "quay.io"
location = "registry.mirrors.zjusct.io/quay.io"

[[registry]]
prefix = "registry.k8s.io"
location = "registry.mirrors.zjusct.io/registry.k8s.io"
```

Add mappings for other proxied registries as needed. This does not configure Docker daemon or Kubernetes' containerd. Prefer fully qualified names:

```console
podman pull docker.io/library/ubuntu:24.04
skopeo inspect docker://registry.k8s.io/pause:3.10
```
</details>

<details>
<summary>containerd, including Kubernetes nodes</summary>

Create `/etc/containerd/certs.d/docker.io/hosts.toml`:

```toml
server = "https://registry-1.docker.io"

[host."https://docker.mirrors.zjusct.io"]
  capabilities = ["pull", "resolve"]
```

Enable `/etc/containerd/certs.d` for the CRI plugin by merging the matching section into `/etc/containerd/config.toml`:

```toml
# containerd 2.x, configuration version 3
[plugins."io.containerd.cri.v1.images".registry]
  config_path = "/etc/containerd/certs.d"

# containerd 1.x, configuration version 2
[plugins."io.containerd.grpc.v1.cri".registry]
  config_path = "/etc/containerd/certs.d"
```

Restart containerd after first changing `config_path`. K3s, RKE2, and similar distributions should use their supported registry configuration mechanism. Use complete proxy names for other registries.
</details>

<details>
<summary>Standalone BuildKit / Docker Buildx</summary>

Add the Docker Hub mirror to `buildkitd.toml`:

```toml
[registry."docker.io"]
  mirrors = ["docker.mirrors.zjusct.io"]
```

Load the configuration and restart buildkitd. For Buildx's `docker-container` driver:

```console
docker buildx create --name zju-mirror --driver docker-container --buildkitd-config ./buildkitd.toml --use
docker buildx inspect --bootstrap
```
</details>
