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 namedsha256-<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
- Write down whether you need a platform, an OCI-native binary, or a minimal registry.
- Pin exact versions (Harbor line + patch, Zot tag, Distribution tag) in your install repo.
- Confirm licence and CNCF status with legal (all three Apache 2.0 on 14 October 2026; only Harbor Graduated).
- Decide storage: filesystem for labs; S3-compatible for shared durability (cross-check MinIO alternatives if you self-host the bucket).
- Enable delete + GC before the disk fills; practise GC in a non-prod project.
- Test referrers with oras attach/discover against your version; do not assume native
/referrerssupport. - Put Hub credentials only on the pull-through component, not on every node.
- Create robot or token identities for CI; rotate them.
- Wire scan or signature policy to admission control, not only to chat alerts.
- Patch within a week when Harbor or Zot publish a security batch; Distribution proxy users should track CVEs that name pull-through.
Common mistakes
- Treating Harbor, Zot and Distribution as interchangeable “Docker registries”.
- Running Distribution v2.8 or early v3.0 as a Hub pull-through without reading the 2026 proxy CVEs.
- Assuming the referrers API exists because oras discover succeeded (tag schema fallback hides a 404).
- Enabling Harbor without planning PostgreSQL backup and Redis loss behaviour.
- Leaving the Harbor admin password at the documented default.
- Skipping GC until the PVC is full, then discovering delete was never enabled.
- Giving every developer a Hub login instead of a central proxy cache.
- Storing raw images without a promotion path, then wondering why production pulled
:latest. - Ignoring robot account scope (“cover all projects”) after the October 2026 Harbor advisories.
- 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).
- About 10:16:52 PM IST. Both registries accepted
GET /v2/with HTTP 200. Zot loggedReleaseTag: 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. - Push.
oras push --plain-httpof a tinygreeting.txtartefact with--artifact-type application/vnd.revisit.hello.v1+jsonto both registries asdrill41/hello:v1. Both returned digestsha256:a44c0ec65f7eb3fdb706a8653bbdb5d80c91a10b40513f9ed73a38b717178bdf. - Attach.
oras attachof a fake SBOM (application/vnd.example.sbom.v1+json) to both. Attach digestsha256:dbf039fabe585634217c61bb13a83ccf733fb4dde2988268f47c1c54a1597e50. Annotationorg.opencontainers.image.created: 2026-10-14T16:47:13Z(about 10:17:13 PM IST). - Discover.
oras discoverlisted the SBOM under both registries. - Native referrers API.
GET /v2/drill41/hello/referrers/<digest>: Distribution HTTP 404 (404 page not found). Zot HTTP 200 withContent-Type: application/vnd.oci.image.index.v1+jsonand one manifest entry carryingartifactType: application/vnd.example.sbom.v1+json. - Tag schema. Distribution
tags/listshowedv1andsha256-a44c0ec65f7e...(referrers tag schema). Zot showed onlyv1. - Delete. crane/oras deleted the subject and referrer manifests. Zot tags became
[]. Distribution still listed thesha256-...referrers tag until GC with--delete-untagged. - Distribution GC (about 10:17:30 PM IST).
registry garbage-collectremoved unreferenced blobs but kept referrers-index material until a second run with--delete-untagged. - 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 reportedgarbage collected blobscount: 3. Disk for the Zot root fell to about 52K (cache.db only). - 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
- goharbor/harbor on GitHub
- Harbor v2.15.4 release
- Harbor v2.15.3 release
- Harbor v2.14.5 release
- Harbor v2.13.6 release
- Harbor v2.15.0 release
- Harbor LICENSE (Apache 2.0)
- Harbor README at v2.15.4
- Harbor docs 2.15 install
- Harbor configure YAML
- Harbor HA Helm
- Harbor garbage collection
- Harbor proxy cache
- Harbor replication
- Harbor vulnerability scanning
- Harbor robot accounts
- Harbor create robot accounts
- Harbor security advisories
- CNCF Harbor project page
- CNCF Harbor graduation announcement
Zot
- project-zot/zot on GitHub
- Zot v2.1.22 release
- Zot v2.1.21 release
- Zot v2.1.20 release
- Zot LICENSE (Apache 2.0)
- Zot README at v2.1.22
- zotregistry.dev
- zotregistry.dev v2.1.22
- Zot security advisories
- CNCF Zot project page
CNCF Distribution
- distribution/distribution on GitHub
- Distribution v3.1.2 release
- Distribution v3.1.1 release
- Distribution v3.1.0 release
- Distribution v3.0.0 release
- Distribution LICENSE (Apache 2.0)
- Distribution README at v3.1.2
- Distribution documentation
- Distribution configuration
- Distribution garbage collection
- Distribution pull-through mirror recipe
- Distribution security advisories
- CNCF Distribution project page
- Docker: donating Distribution to the CNCF
OCI, clients and Hub limits
- OCI distribution-spec repository
- OCI distribution-spec v1.1.0
- OCI distribution-spec v1.1.1
- OCI Image and Distribution Specs v1.1 announcement
- oras.land
- oras docs
- oras v1.3.4 release
- sigstore/cosign
- Notary Project
- notation on GitHub
- Docker Hub pull usage and limits
- Docker Hub usage
Security records
- GHSA-2phj-cp9f-qq6w
- GHSA-w5fq-xrhj-j7g2
- GHSA-c7hr-vm67-mm6v
- GHSA-9w95-g7vg-45v6
- GHSA-685w-q87j-wqw3
- GHSA-3p65-76g6-3w7r
- GHSA-f2g3-hh2r-cwgc
- GHSA-6pjf-3r9x-m592
- GHSA-phw4-mc57-4hwc
- CVE-2026-33540 on cve.org
- CVE-2026-35172 on cve.org
- CVE-2026-41888 on cve.org
- CVE-2026-85747 on cve.org
- CVE-2026-4404 on cve.org
- CVE-2026-61833 on cve.org
- CVE-2025-24976 on cve.org
- CVE-2025-48374 on cve.org
- CVE-2026-31801 on cve.org
- OSV database
Internal
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 moreFeature 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 moreFluent 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