Skip to content

Container Registry

Service ownership

Owner: container-platform (k8s-pm@clouddigit.ai) — Status: GA — Last audited: 2026-05-11

Private OCI-compliant container registry with image scanning and project-scoped access control.

What it is

A registry for container images and OCI artefacts. Push from docker, podman, buildah, nerdctl, anything that speaks OCI. Pull from any K8s cluster (Cloud Digit or otherwise).

Endpoints

Region Endpoint
bd-dha-1 registry.bd-dha-1.clouddigit.ai
bd-ctg-1 registry.bd-ctg-1.clouddigit.ai
bd-syl-1 registry.bd-syl-1.clouddigit.ai

Features

  • Project-scoped repos<project>/<repo>:<tag>
  • Vulnerability scanning — Trivy-based, on push
  • Image signing — Cosign / Notary v2 supported
  • Multi-arch manifests — supported (linux/amd64 + linux/arm64)
  • Geo-replication — replicate repos across regions
  • Garbage collection — scheduled, retention-policy-driven
  • Helm charts as OCI artifacts

Authentication

  • Long-lived robot accounts (per project)
  • Short-lived tokens via Cloud Digit IAM
  • Native pull from Managed Kubernetes — no imagePullSecrets needed (uses cluster identity)

Pricing

  • Storage — per GiB-month
  • Egress — free to Cloud Digit infrastructure; international egress metered
  • Vulnerability scanning — included

See Pricing.

Operate this service

OCI-compatible registry for Docker / OCI images, integrated with the Cloud Digit IAM.

Project / repo layout

  • Project = the team or app
  • Repo = one image stream (acme/web-frontend, acme/billing-api)

Don't put unrelated images in the same project — IAM is project-scoped.

IAM

Role Can do
registry.viewer List repos, view tags
registry.puller Pull images
registry.pusher Push images
registry.admin Above + delete tags, configure scanning, retention

CI/CD systems get registry.pusher via service-account tokens; runtime clusters get registry.puller.

Scanning

Vulnerability scanning runs on every push. Configure block-on-severity:

```bash cd registry policy set --project acme --block-on critical

Pushes with CRITICAL CVEs are rejected

```

Allowlist exceptions for accepted-risk findings.

Image signing (cosign)

For production runtime: require signed images via Kyverno or Sigstore policy controller:

bash cosign sign --key cosign.key registry.cloudigit.bd/acme/web-frontend:v1.2.3

Cluster admission rejects unsigned images.

Retention

Configure to prevent registry bloat:

bash cd registry retention set --project acme \ --keep-last 30 \ --keep-tagged 'release-*,main' \ --delete-untagged-older-than 7d

Common pattern: keep all release tags forever; keep last 30 of dev tags; sweep untagged after 7 days.

Metrics

Metric Notes
registry.pushes_per_day Should match CI activity
registry.pulls_per_day Should match deploy + scale events
registry.bytes_stored Plan capacity
registry.scan_critical_findings Should trend to 0
registry.signed_pulls_pct Should be 100% for prod clusters

Push from CI

bash docker login registry.cloudigit.bd -u serviceaccount -p $REGISTRY_TOKEN docker push registry.cloudigit.bd/acme/web-frontend:$CI_COMMIT_SHA

Tokens are project-scoped, with TTL ≤ 90 days. Rotate via API tokens.

Pull from K8s

yaml imagePullSecrets: - name: cd-registry-acme

The secret holds the token. For multi-project pulls, multiple secrets — or a federated principal.

Image promotion

Promote a tested image from staging registry to prod:

bash cd registry image promote \ --from acme-staging/web-frontend:v1.2.3 \ --to acme-prod/web-frontend:v1.2.3

Promotion preserves the digest — no re-build, no re-scan.

Mirroring

For air-gapped clusters: mirror upstream registries (Docker Hub, gcr.io) to a Cloud Digit project:

bash cd registry mirror enable --project acme-deps --upstream docker.io

Then pull via registry.cloudigit.bd/acme-deps/library/nginx:1.27 — same image, but proxied through your registry.

Garbage collection

Retention policy runs nightly. Force immediate GC after a bulk delete:

bash cd registry gc run --project acme

GC is online; doesn't affect pushes/pulls during execution.

denied: requested access to the resource is denied

Most common — auth issue:

  1. Token expired? Generate a new one via console
  2. Token scoped to wrong project?
  3. Role lacks pull/push permission?
  4. Image path typo — acme/web vs acme-prod/web?

manifest unknown

The tag doesn't exist (anymore):

  • Retention policy may have purged it. Check cd registry image list --repo acme/web.
  • Typo in tag name
  • Image was pushed but deleted

Push fails: "blocked by scan policy"

ERROR: push rejected: image contains CRITICAL vulnerability CVE-2025-XXXX

Either: - Update the base image / dependency - Allowlist the CVE (with justification): bash cd registry scan allowlist add --cve CVE-2025-XXXX --reason "patched in app layer" --expires 2026-08-01

Allowlist entries should expire; renewal forces re-review.

Slow pulls

Cause Fix
Pulling from another region Use local-region registry endpoint
Large image (multi-GB) Multi-stage build to slim
Many small layers Squash layers in final stage
Network plane saturated Pull via dedicated CDN backed registry pull-through cache

Image signature verification failed

ERROR: image is not signed by trusted key

Cosign signature missing or signed by an unauthorized key. Either: - Sign before pushing (CI step) - Resign manually: cosign sign --key <prod-key> <image> - Loosen the policy temporarily (dev clusters only)

Mirror not pulling upstream

Mirror failures (rate limit, upstream auth):

bash cd registry mirror status --project acme-deps --upstream docker.io

Docker Hub now rate-limits anonymous pulls — authenticate the mirror with a Docker Hub Pro account.

Storage growing unexpectedly

Layer dedup means total storage = unique layer count, not image count. But: - Pushing the same dependency in many slightly different images bloats storage - Untagged images (orphaned by docker push :latest) accumulate

Audit: bash cd registry storage report --project acme cd registry image list --untagged --older-than 7d