Container registries in 2026: revisit Harbor, Zot and CNCF Distribution before you push another image

Picture a product engineering team in Bengaluru that runs about forty microservices on Kubernetes for a B2B payments product used by NBFCs across Karnataka and Maharashtra (an invented example, not a real client). Builds land in GitLab CI several times a day. Nodes pull base images from Docker Hub, and anonymous Hub pulls keep hitting the documented 100-pull-per-six-hour ceiling, so the platform team wants a self-hosted registry that can also act as a pull-through cache. Security wants vulnerability scans before promotion. Two clusters in different AZs need the same signed images. One engineer wants Harbor, because “we need a UI, RBAC and scanning”. Another wants Zot, because “one binary, OCI-native, no Postgres”. A third wants plain CNCF Distribution (the project formerly known as docker/distribution, the familiar registry:2 / registry:3 image), because “we only need push and pull”. Legal asks whether all three are still Apache 2.0 and what CNCF status each carries.

These three projects overlap on the wire protocol, but they are not three wrappers around the same product. Harbor is a full registry platform: projects, RBAC, robot accounts, replication, proxy cache, vulnerability scanning (Trivy by default), a web UI, and dependencies that normally include PostgreSQL and Redis. Zot is an OCI-native registry that ships as a single Go binary (full or minimal builds), stores content in OCI layout, and adds optional extensions for search, sync, scanning and a UI. CNCF Distribution is the minimal reference registry and core library behind many public registries: push, pull, storage drivers, an optional pull-through proxy, and garbage collection that you run yourself. This post compares where they stand on 14 October 2026: releases, OCI Distribution Spec 1.1 referrers, storage and GC, auth, security advisories, governance, and a decision guide. Facts come from GitHub releases and LICENSE files, project docs, CNCF project pages, and advisory records cross-checked against GitHub Security Advisories, OSV and cve.org. The drill near the end is my own run of Zot v2.1.22 (minimal) and Distribution v3.1.2 on loopback with oras and crane. Harbor needs Docker Compose or Kubernetes; this shared box has no Docker, so Harbor was not drilled. How you build images is a separate topic; see the earlier post on BuildKit, Buildah and Kaniko. This post is about where those images live after the build.

The short version

  • Decide first what problem you have. A team that only needs a private push/pull endpoint can stay on Distribution. A team that wants OCI referrers, a small footprint and optional extensions should look at Zot. A team that wants projects, RBAC, replication, scanning and a UI as one product is in Harbor territory.
  • Harbor (goharbor/harbor) is at v2.15.4 (9 October 2026, 8:58 AM IST), with maintained lines at v2.14.5 and v2.13.6 (both 6 October 2026). CNCF Graduated (accepted 31 July 2018, graduated 15 June 2020). Apache 2.0. Needs PostgreSQL and Redis in typical installs; scanning uses Trivy.
  • Zot (project-zot/zot) is at v2.1.22 (6 October 2026, 10:20 PM IST). CNCF Sandbox (accepted 13 December 2022). Apache 2.0. Single binary; the minimal build I ran had GC and the Distribution Spec API, without search/UI/sync/scan extensions.
  • CNCF Distribution (distribution/distribution) is at v3.1.2 (24 September 2026, 5:51 PM IST). CNCF Sandbox (accepted 26 January 2021). Apache 2.0. The v3 line started with v3.0.0 (3 April 2025). It is the reference server and a library used by Harbor and several public registries.
  • On OCI Distribution Spec 1.1, the referrers API (GET /v2/<name>/referrers/<digest>) is the standard way to list signatures and SBOMs attached to an image. In my drill, Zot returned HTTP 200 with an OCI index; Distribution v3.1.2 returned HTTP 404 for that path, and oras fell back to the referrers tag schema (a tag named sha256-<digest>). Clients still worked; the server behaviour differed.
  • Security history is active in 2026. Harbor published a batch of advisories on 6 October 2026 fixed in 2.13.6 / 2.14.5 / 2.15.3+. Zot had multiple high and one critical advisory through mid-2026, with fixes landing by 2.1.21 / 2.1.22 for the ones I checked that listed <= 2.1.20. Distribution fixed several CVEs across v3.0.0-rc.3, v3.1.0, v3.1.1 and v3.1.2. Pin patch versions.

Where things stand on 14 October 2026

Dates are GitHub release published_at, converted from UTC to IST (UTC+5:30). Licences are from the LICENSE files on the default branch and at the tagged releases. None of the listed current releases is marked prerelease (Harbor also had v2.14.6-rc1 on 13 October 2026; I did not treat RCs as current).

Project

Release

Date (IST)

Notes

Licence

Harbor (goharbor/harbor)

v2.15.4

9 October 2026, 8:58 AM

Current 2.15 line; Trivy 0.75.0 / adapter 0.39.1; distribution component v2.8.3-harbor.2

Apache 2.0

Harbor

v2.15.3

6 October 2026, 6:41 PM

Security fixes for the 6 Oct advisory batch

Apache 2.0

Harbor

v2.14.5

6 October 2026, 9:17 PM

Current 2.14 line with the same advisory batch

Apache 2.0

Harbor

v2.13.6

6 October 2026, 9:18 PM

Current 2.13 line with the same advisory batch

Apache 2.0

Harbor

v2.15.0

20 March 2026, 10:06 AM

Start of 2.15; Cosign-signed release artefacts

Apache 2.0

Zot (project-zot/zot)

v2.1.22

6 October 2026, 10:20 PM

Current release; sparse multi-arch sync filter, auth and storage fixes

Apache 2.0

Zot

v2.1.21

7 September 2026, 12:14 AM

Previous patch

Apache 2.0

Zot

v2.1.20

4 August 2026, 11:21 PM

Several advisories list <= 2.1.20 as vulnerable

Apache 2.0

Distribution (distribution/distribution)

v3.1.2

24 September 2026, 5:51 PM

Current; fixes CVE-2026-85747; Go 1.26+ to build from source

Apache 2.0

Distribution

v3.1.1

1 May 2026, 9:21 PM

Fixes CVE-2026-41888; S3 Express One Zone

Apache 2.0

Distribution

v3.1.0

6 April 2026, 10:39 PM

Fixes CVE-2026-35172 and CVE-2026-33540; tag pagination

Apache 2.0

Distribution

v3.0.0

3 April 2025, 11:55 AM

First stable v3; OSS and Swift drivers removed; config path /etc/distribution/config.yml

Apache 2.0

Practical notes. Harbor keeps three minor lines hot with security patches on the same day, so a platform team must know which line it is on before reading an advisory. Zot releases roughly monthly on the 2.1 line. Distribution’s v3 line is still young compared with the long registry:2 era; if you are still on v2.8.x, plan a deliberate upgrade and read the v3 deprecations. GitHub stars on fetch day were about 29,546 (Harbor), 10,648 (Distribution) and 2,865 (Zot); stars measure attention, not fitness for your cluster.

Timeline

Date (IST)

Event

22 December 2014

distribution/distribution repository created on GitHub (as the Docker Registry 2.x codebase)

28 January 2016

goharbor/harbor repository created on GitHub

21 June 2019

project-zot/zot repository created on GitHub

31 July 2018

Harbor accepted into CNCF

14 November 2018

Harbor moved to CNCF Incubating

15 June 2020

Harbor moved to CNCF Graduated (announcement dated 23 June 2020)

26 January 2021

Distribution accepted into CNCF at Sandbox

13 December 2022

Zot accepted into CNCF at Sandbox

15 February 2024

OCI Distribution Spec v1.1.0 (referrers API)

29 January 2025

OCI Distribution Spec v1.1.1

3 April 2025

Distribution v3.0.0 stable

20 March 2026

Harbor v2.15.0

6 April 2026

Distribution v3.1.0 (CVE-2026-35172, CVE-2026-33540)

1 May 2026

Distribution v3.1.1 (CVE-2026-41888)

24 September 2026

Distribution v3.1.2 (CVE-2026-85747)

6 October 2026

Harbor security patch set 2.13.6 / 2.14.5 / 2.15.3; Zot v2.1.22

9 October 2026

Harbor v2.15.4

Harbor is the graduated CNCF registry product. Distribution and Zot are both Sandbox. That maturity label is governance and adoption signal, not a performance score.

First question: what problem are you solving?

Before comparing features, the Bengaluru review has to agree on which of three situations it is in.

Private push and pull only. CI pushes, clusters pull, no product requirement for a portal, replication policies or built-in scanning. Distribution is enough. You still need TLS, auth (often a separate token service or an ingress that terminates identity), storage that you can back up, and a GC runbook.

OCI artifacts and a small operations surface. You care about signatures, SBOMs and other referrers, you want one binary or a small Helm chart, and you are willing to compose scanning and policy from other tools (cosign, notation, Kyverno, your CI). Zot fits this shape. Pick the full binary if you want extensions; the minimal binary if you want a thin registry.

Platform registry. Several teams share one registry, each with projects and roles, robot accounts for CI, replication to a DR site, proxy cache for Docker Hub, and scan-on-push with promotion rules. Harbor is built for that. Accept PostgreSQL, Redis and the larger install surface as part of the product.

The payments team in our example is closest to the third situation, with a strong pull-through-cache need from the second. That split decides more than any feature table.

What each project actually is

Harbor v2.15.4

Harbor calls itself an open source trusted cloud native registry that stores, signs and scans content. Its README feature list is the practical map: cloud native registry for images and Helm charts, role based access control through projects, policy based replication, vulnerability scanning with policy checks, LDAP/AD and OIDC, image deletion and garbage collection, Notary / content trust support, a graphical portal, auditing and a REST API. Deployments use Docker Compose on a Linux host (docs ask for Docker 20.10.10-ce+ and docker-compose 1.18.0+) or the Harbor Helm chart / operator on Kubernetes.

Under the covers, a typical install still depends on PostgreSQL for metadata and Redis for cache and job coordination, plus the registry service itself (Harbor vendors a Distribution-based component; v2.15.4 notes distribution at v2.8.3-harbor.2), a core API, a job service, a portal, and a scanner adapter. Trivy is the scanner path documented for current releases; v2.15.4 bumps Trivy to 0.75.0 and the Trivy adapter to 0.39.1. Robot accounts give CI a non-human identity with scoped permissions. Proxy cache projects pull and cache from upstream registries such as Docker Hub, which is how many Indian platform teams absorb Hub rate limits without giving every node a Hub login. Replication pushes or pulls artefacts between Harbor instances or compatible registries.

Harbor is CNCF Graduated. The licence at the repository and tagged releases is Apache 2.0. From v2.15.0, release artefacts are Cosign-signed. It is the “registry as a product” option in this comparison.

Zot v2.1.22

Zot describes itself as a production-ready, vendor-neutral OCI image registry: images in OCI image format, Distribution Spec on the wire. Documentation lives at zotregistry.dev. Releases ship full, minimal and debug binaries per OS and architecture, plus zli and zb helpers. The minimal binary I ran logged BinaryType: minimal and skipped search, metrics, scrub, sync, image-trust, swagger, GraphQL playground, UI and related routes, while still serving /v2/ and running storage GC.

Zot is OCI-first by design. Config can declare a Distribution Spec version (my drill used "distSpecVersion": "1.1.1"). Storage defaults to a filesystem root in OCI layout; S3-compatible backends are supported in the wider project. Extensions (in the full binary) add search, sync (pull from other registries), scanning, UI and more. Auth options in config include htpasswd, LDAP, bearer, OpenID and API keys; the minimal binary still exposes the auth config surface even when extensions are compiled out.

Zot is CNCF Sandbox (accepted 13 December 2022). The licence is Apache 2.0. It is the “one binary, OCI-native” option: less platform than Harbor, more OCI behaviour out of the box than Distribution v3.1.2 showed in my referrers check.

CNCF Distribution v3.1.2

Distribution is the toolkit to pack, ship, store and deliver container content. The README states the goal clearly: a simple, secure, scalable base for building a large-scale registry or running a simple private registry, and a core library for operators including Docker Hub, GitHub Container Registry, GitLab Container Registry, DigitalOcean Container Registry and Harbor. The server you run is commonly still called “the registry”.

v3 is a break from the long registry:2 line. v3.0.0 removed the OSS and Swift storage drivers, replaced docker/libtrust with go-jose, changed the default config path to /etc/distribution/config.yml, and moved the reference package to github.com/distribution/reference. Storage drivers that remain include filesystem, S3, Azure and others documented in the configuration guide. Features that matter day to day: the Registry HTTP API, optional pull-through cache / proxy mirroring, delete support when storage.delete.enabled is true, and a registry garbage-collect command that you schedule yourself. Auth is typically token-based or htpasswd via config; there is no Harbor-style project RBAC UI.

Distribution is CNCF Sandbox (accepted 26 January 2021). Apache 2.0. It is the “minimal reference” option: excellent as a library and as a simple registry, incomplete as a multi-tenant platform.

Comparison tables

Shape and operations

Question

Harbor

Zot

Distribution

Primary shape

Full platform (UI, RBAC, jobs, scanning)

OCI-native registry binary (+ extensions)

Minimal reference registry + library

Typical dependencies

PostgreSQL, Redis, registry, portal, jobservice, scanner

Single process (optional S3, etc.)

Single process (+ optional Redis cache)

Install paths

Docker Compose, Helm, operator

Binary, containers, Helm (project docs)

Binary, official image registry:3

CNCF status

Graduated

Sandbox

Sandbox

Licence

Apache 2.0

Apache 2.0

Apache 2.0

Built-in UI

Yes

Extension / full binary

No

Built-in vulnerability scan

Yes (Trivy path)

Extension / full binary

No

Replication / sync

Policy-based replication

Sync extension

No product replication; proxy is pull-through

Robot / CI accounts

First-class robot accounts

API keys / tokens depending on auth config

Whatever you bolt on (htpasswd, token service)

OCI Distribution Spec 1.1 and referrers

Need

Harbor

Zot

Distribution v3.1.2

Push/pull OCI images and artefacts

Yes

Yes

Yes

Native GET .../referrers/{digest}

Implemented in Harbor’s registry handlers (OCI index response)

Yes in my drill (HTTP 200, OCI index)

HTTP 404 in my drill; clients use referrers tag schema

oras attach / discover

Supported in practice via Harbor’s accessory model

Worked in my drill

Discover worked via tag schema fallback

Signatures / SBOMs

Cosign/Notation as clients; Notary/content-trust policies in product

Clients + optional trust extensions

Clients only; registry stores manifests

OCI Distribution Spec v1.1.0 (15 February 2024) and v1.1.1 (29 January 2025) define the referrers API so that a signature or SBOM can point at a subject digest and be listed without a dedicated tag namespace. Until every registry serves that API, clients such as oras must fall back to the tag schema. Plan for both behaviours in automation.

Storage, GC, proxy and HA

Need

Harbor

Zot

Distribution

Filesystem storage

Yes

Yes (OCI layout)

Yes

S3 / MinIO style backend

Via storage config (see also our MinIO alternatives post)

Supported in project

S3 driver (and others); S3 Express in v3.1.1

Garbage collection

Admin GC jobs in product

In-process GC (interval/delay in config)

registry garbage-collect; optional --delete-untagged

Pull-through / proxy cache

Proxy cache projects

Sync extension (different model)

Built-in proxy / mirror recipe

Multi-instance HA

Helm HA docs; shared DB and Redis

Scale-out / cluster features in project

Stateless replicas in front of shared storage; careful with HTTP secret

Symptom to shape

You notice

Usually means

Reasonable direction

Nodes fail Hub pulls with HTTP 429

Rate limit / shared egress IP problem

Harbor proxy cache, or Distribution pull-through, plus authenticated Hub pulls where policy allows

Several teams share one registry and fight over who can delete tags

Missing tenancy and RBAC

Harbor projects and robots

You need signatures and SBOMs discoverable beside the image

Referrers workflow

Zot or Harbor; test the referrers API, do not assume Distribution v3.1.2 serves it natively

You want the smallest binary for an air-gapped lab

Minimal registry

Distribution or Zot minimal

Auditors ask for scan-on-push and promotion gates

Policy in the registry product

Harbor, or Zot full + external policy

A worked example: one artefact, three registries

Invented flow for the Bengaluru team. CI builds payments/api:1.4.2, signs it with cosign or notation, attaches an SBOM, and wants clusters to pull only if the signature and SBOM are present.

With Distribution, you run the registry, enable storage.delete.enabled if you will GC, push with oras or your client, and attach the SBOM. Discovery may use the referrers tag schema until the server gains a native referrers endpoint. Policy (“must have signature”) lives in the cluster admission layer, not in Distribution.

With Zot, you push and attach the same way. In my drill the native referrers API listed the SBOM artefact type immediately. Policy can still live in Kubernetes; Zot’s job is to store and list the graph correctly.

With Harbor, you create a project, a robot account for GitLab CI, enable scan-on-push, and optionally a replication rule to the DR Harbor. The portal shows the artefact; promotion between project stages becomes a Harbor workflow rather than only a pipeline convention.

The image build step is unchanged across all three; keep using BuildKit or your chosen builder from the earlier image-builds post.

Security (verified advisories)

I checked GitHub repository advisories, GitHub global advisories where linked, OSV queries for the Go module paths, and cve.org records on 14 October 2026. NVD HTML pages returned HTTP 403 from this environment, so CVE confirmation below uses cve.org and GHSA, not NVD pages.

Harbor

On 6 October 2026 Harbor published a large advisory batch. Several high issues share the same version ranges: vulnerable below 2.13.6, in 2.14.0 to below 2.14.5, and in 2.15.0 to below 2.15.3. Examples: GHSA-2phj-cp9f-qq6w (SSRF in webhook delivery), GHSA-w5fq-xrhj-j7g2 (system robot with user:update can become administrator), GHSA-xq2m-cj8w-56v5 (robot “cover all projects” scope collapse), GHSA-xvh7-74g6-29xw (auth-proxy identity named admin), GHSA-qj39-pjf2-wmrc (path traversal in distribution endpoints). Medium issues in the same batch include pull-policy bypass via User-Agent (GHSA-wrw5-gmvj-gf23) and replication Link-header SSRF (GHSA-xgp2-5vxg-rgh2). v2.15.4, v2.14.5 and v2.13.6 are the patch releases to move to on those lines.

Older named CVEs still matter for lagging installs: CVE-2026-4404 (default password concern, GHSA-56j8-6qr5-cg75 / GHSA-hj7x-hmf2-hc2p), CVE-2025-30086 (ORM leak), CVE-2025-32019 (XSS in repository description), CVE-2024-22278, CVE-2024-22244.

Zot

Zot’s 2026 advisory list is busy for a Sandbox project. GHSA-9w95-g7vg-45v6 (critical): v2.1.18 digest multi-tag push bypasses update authorisation. GHSA-c7hr-vm67-mm6v (high): HEAD on a blob authorised as read but creates repository and writes a blob (<= 2.1.20). GHSA-prmc-5wf3-9593 (high): unbounded GraphQL fanout on 2.1.20. GHSA-82rc-37x2-7w36 (high): incomplete fix for cross-repository blob reuse (<= 2.1.20). CVE-2026-61833 / GHSA-qg67-7m6v-qg25 (high): bearer auth maps DELETE to push scope (<= v2.1.15). CVE-2026-31801 / GHSA-85jx-fm8m-x8c6 (high): create-only policy allows overwrite attempts. CVE-2025-48374 / GHSA-c37v-3c8w-crq8 (high): logged secret. Treat v2.1.22 (or at least newer than 2.1.20 for the September batch) as the floor unless you have verified otherwise against each GHSA.

Distribution

CVE / GHSA

Severity

Summary

Fixed as of

CVE-2026-85747 / GHSA-685w-q87j-wqw3

medium

Client manifests.Get() did not verify body against requested digest (hurts pull-through / digest pinning)

v3.1.2 (patched_versions >=3.1.2)

CVE-2026-41888 / GHSA-6pjf-3r9x-m592

medium

Tag deletion bypassed storage.delete.enabled

v3.1.1 (release notes)

CVE-2026-35172 / GHSA-f2g3-hh2r-cwgc

high

Stale blob access via Redis descriptor cache invalidation

v3.1.0

CVE-2026-33540 / GHSA-3p65-76g6-3w7r

high

Pull-through cache credential exfiltration via WWW-Authenticate bearer realm

v3.1.0

CVE-2025-24976 / GHSA-phw4-mc57-4hwc

high

Token auth allowed injecting an untrusted signing key in a JWT

v3.0.0-rc.3

If you still run Distribution v2.8.x or early v3.0.x as a pull-through cache, prioritise the upgrade. The 2026 CVEs specifically touch proxy and delete behaviour.

Shared controls

  • TLS everywhere; do not leave a registry on plain HTTP outside a lab loopback.
  • Short-lived robot or token credentials in CI; never a personal password.
  • Separate credentials for pull-through to Docker Hub; watch Hub’s documented limits (unauthenticated 100 pulls / 6 hours per IPv4 or IPv6 /64; Personal 200; Pro/Team/Business unlimited, per Docker’s pull usage docs retrieved on 14 October 2026).
  • Admission policy in Kubernetes (see the Kyverno / Gatekeeper / ValidatingAdmissionPolicy post) for signature and base-image rules.
  • Secrets for registry admin and robot accounts in a secrets manager (see Vault / OpenBao).

Decision guide

Situation

Lean towards

Why

Multi-team platform registry with audit and scan-on-push

Harbor

Projects, robots, scanning and replication are product features

OCI artefacts, referrers, small footprint

Zot

Single binary; native referrers in my drill

Simplest private registry or embedding a library

Distribution

Minimal server; upstream library for Harbor and public registries

Primary pain is Docker Hub 429s

Harbor proxy cache or Distribution pull-through

Both can cache upstream; Harbor adds tenancy

Air-gapped lab, no Postgres

Zot minimal or Distribution

No mandatory external database

CNCF Graduated requirement from risk committee

Harbor

Only Graduated project of the three

Bengaluru recommendation (invented). Start with Harbor for the shared platform registry: proxy cache for Hub, robot accounts for GitLab, Trivy on push, replication to the second AZ. Use Zot only if the team explicitly rejects Harbor’s dependency footprint and is ready to own scanning and RBAC elsewhere. Keep Distribution for throwaway CI registries and local kind/k3d labs, on v3.1.2+, not as the company-wide source of truth.

Checklist

  1. Write down whether you need a platform, an OCI-native binary, or a minimal registry.
  2. Pin exact versions (Harbor line + patch, Zot tag, Distribution tag) in your install repo.
  3. Confirm licence and CNCF status with legal (all three Apache 2.0 on 14 October 2026; only Harbor Graduated).
  4. Decide storage: filesystem for labs; S3-compatible for shared durability (cross-check MinIO alternatives if you self-host the bucket).
  5. Enable delete + GC before the disk fills; practise GC in a non-prod project.
  6. Test referrers with oras attach/discover against your version; do not assume native /referrers support.
  7. Put Hub credentials only on the pull-through component, not on every node.
  8. Create robot or token identities for CI; rotate them.
  9. Wire scan or signature policy to admission control, not only to chat alerts.
  10. Patch within a week when Harbor or Zot publish a security batch; Distribution proxy users should track CVEs that name pull-through.

Common mistakes

  1. Treating Harbor, Zot and Distribution as interchangeable “Docker registries”.
  2. Running Distribution v2.8 or early v3.0 as a Hub pull-through without reading the 2026 proxy CVEs.
  3. Assuming the referrers API exists because oras discover succeeded (tag schema fallback hides a 404).
  4. Enabling Harbor without planning PostgreSQL backup and Redis loss behaviour.
  5. Leaving the Harbor admin password at the documented default.
  6. Skipping GC until the PVC is full, then discovering delete was never enabled.
  7. Giving every developer a Hub login instead of a central proxy cache.
  8. Storing raw images without a promotion path, then wondering why production pulled :latest.
  9. Ignoring robot account scope (“cover all projects”) after the October 2026 Harbor advisories.
  10. Building a custom UI on Distribution when Harbor already solved tenancy, then underestimating authz bugs.

A drill I ran on 14 October 2026

Shared VM, no Docker (docker not installed). Port 8766 left untouched (local HTML preview server). I ran Zot v2.1.22 linux-amd64-minimal on 127.0.0.1:18081 and Distribution v3.1.2 on 127.0.0.1:18082, with oras 1.3.4 and crane 0.22.1. Checksums: Distribution tarball SHA-256 matched the release .sha256 file (40df2224d410f72ae425c3371873b078bbdbda3b8b612be9571f0e6751f3acc8); Zot minimal matched checksums.sha256.txt (a053169f97b4ceaa051e054d53971799188a398cb36acbaf5e08622ec8664c44). Harbor was not drilled (needs Docker Compose or Kubernetes).

  1. About 10:16:52 PM IST. Both registries accepted GET /v2/ with HTTP 200. Zot logged ReleaseTag: v2.1.22, BinaryType: minimal, distSpecVersion: 1.1.1, GC enabled with 30s interval and 1s delay, and warnings that search/UI/sync/scan extensions are not in the minimal binary.
  2. Push. oras push --plain-http of a tiny greeting.txt artefact with --artifact-type application/vnd.revisit.hello.v1+json to both registries as drill41/hello:v1. Both returned digest sha256:a44c0ec65f7eb3fdb706a8653bbdb5d80c91a10b40513f9ed73a38b717178bdf.
  3. Attach. oras attach of a fake SBOM (application/vnd.example.sbom.v1+json) to both. Attach digest sha256:dbf039fabe585634217c61bb13a83ccf733fb4dde2988268f47c1c54a1597e50. Annotation org.opencontainers.image.created: 2026-10-14T16:47:13Z (about 10:17:13 PM IST).
  4. Discover. oras discover listed the SBOM under both registries.
  5. Native referrers API. GET /v2/drill41/hello/referrers/<digest>: Distribution HTTP 404 (404 page not found). Zot HTTP 200 with Content-Type: application/vnd.oci.image.index.v1+json and one manifest entry carrying artifactType: application/vnd.example.sbom.v1+json.
  6. Tag schema. Distribution tags/list showed v1 and sha256-a44c0ec65f7e... (referrers tag schema). Zot showed only v1.
  7. Delete. crane/oras deleted the subject and referrer manifests. Zot tags became []. Distribution still listed the sha256-... referrers tag until GC with --delete-untagged.
  8. Distribution GC (about 10:17:30 PM IST). registry garbage-collect removed unreferenced blobs but kept referrers-index material until a second run with --delete-untagged.
  9. Zot GC. A run at 10:17:22 PM IST (before delete finished) reported count: 0. A later run at 10:18:12 PM IST reported garbage collected blobs count: 3. Disk for the Zot root fell to about 52K (cache.db only).
  10. Stop. Both registry processes killed; ports 18081/18082 closed; port 8766 still serving.

Surprise worth keeping: oras can hide a missing referrers API. Always curl the native endpoint when you are writing supply-chain automation. Second surprise: Distribution’s referrers tag schema leaves tags that ordinary manifest deletes do not remove; you need GC with --delete-untagged (or an explicit tag delete) to tidy them.

Artefacts under drill41/ on the writer workstation: configs, logs, checksums, notes. Not done: Harbor, Zot full binary extensions, real cosign/notation signing, S3 backends, pull-through to Docker Hub, HA, exploit reproduction.

Unlearn

  • Unlearn “a registry is just docker run registry:2”. In 2026 the choice is platform vs OCI-native vs minimal, and v3 is not a drop-in of every v2 habit.
  • Unlearn assuming referrers work the same on every server because the client succeeded.
  • Unlearn treating CNCF Sandbox and Graduated as the same risk label.
  • Unlearn postponing GC until storage alerts fire.
  • Unlearn giving every cluster node a Docker Hub login as the only answer to rate limits.

Re-learn

  • Re-learn the OCI Distribution Spec 1.1 referrers model and the tag schema fallback.
  • Re-learn Harbor’s dependency surface (PostgreSQL, Redis, jobservice, scanner) before promising a “quick” install.
  • Re-learn Zot minimal vs full binaries so you do not expect UI or sync from minimal.
  • Re-learn Distribution delete flags and garbage-collect --delete-untagged.
  • Re-learn patch cadence: Harbor’s 6 October 2026 batch and Distribution’s proxy CVEs are why version pins matter.

Closing

Self-hosted container registries in 2026 still look like a single checkbox until Hub returns 429, a signature cannot be discovered, or a security advisory lands on a Friday. Harbor is the graduated platform when you want projects, robots, scanning and replication as one product. Zot is the OCI-native binary when you want referrers and a small footprint, with extensions when you need them. CNCF Distribution remains the minimal reference registry and the library under much of the ecosystem, now on a v3 line you should keep patched. The Bengaluru review becomes useful once it separates rate-limit caching from multi-tenant policy, and the wire protocol from the product. Learn what each shape owns. Unlearn treating them as synonyms. Re-learn referrers and GC on a loopback before you touch production. Practise a push, an attach, a discover and a delete on a throwaway registry. Apply the registry that matches your tenancy and supply-chain needs, and only then push another image.

Sources

Harbor

Zot

CNCF Distribution

OCI, clients and Hub limits

Security records

Internal

comments powered by Disqus

Releted Posts

Kubernetes autoscaling in 2026: revisit Karpenter, Cluster Autoscaler and KEDA before you scale another node

Picture a mid-size ecommerce SaaS in Ahmedabad with about 2,200 active sellers (an invented example, not a real client). Its platform team of eight runs checkout, catalogue, search and about 55 other services on Kubernetes on a public cloud.

Read more

Feature flags in 2026: revisit Unleash, Flagsmith and GrowthBook before you hard-code another release toggle

Picture a test-preparation and online classes platform in Jaipur (an invented example, not a real client). Students use an Android app, an iOS app and a React web app.

Read more

Fluent Bit, Vector and the OpenTelemetry Collector: revisit your log pipeline before you ship more logs

A logistics company in Pune runs about 600 pods across three Kubernetes clusters. A Fluentd DaemonSet, set up in 2019 with a dozen Ruby plugins, ships about 25 crore log lines a day to Loki.

Read more