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.
Related¶
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.
Related¶
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.
Related¶
denied: requested access to the resource is denied¶
Most common — auth issue:
- Token expired? Generate a new one via console
- Token scoped to wrong project?
- Role lacks pull/push permission?
- Image path typo —
acme/webvsacme-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