Chapter 23Lesson 01~305 minutes

Container Registry, OCI Images, Cleanup, Authentication, Vulnerability Scanning, and Retention: Concepts, Architecture, and Mental Model

Model GitLab Container Registry state using OCI repositories, mutable tags, immutable digests, manifests, authentication scopes, cleanup policy, scanning evidence, and Self-Managed storage boundaries.

Mental modelOCIContainer RegistryDigestTagsTrust

Learning objectives

  • Distinguish project registry repositories, OCI manifests/indexes, tags, and digests.
  • Explain why digest identity survives tag movement and supports rollback/audit.
  • Choose short-lived CI registry identity versus persistent registry tokens with least privilege.
  • Separate cleanup policy from physical storage garbage collection.
  • Bind container-scanning evidence to the exact image identity it assessed.
Availability baseline (verified 2026-08-22 against current GitLab 19.3 documentation). The integrated Container Registry is Free/Premium/Ultimate on GitLab.com, Self-Managed, and Dedicated; Self-Managed administrators must enable and operate it. Registry authentication supports job-scoped CI credentials and token credentials with registry scopes. Cleanup policies are Free across all three offerings. Container scanning is Free/Premium/Ultimate, but some vulnerability-management presentation/governance capabilities vary by tier. Protected container repositories are Free across all three offerings. Protected container tags are Free on GitLab.com and Self-Managed with the current registry backend prerequisites. Immutable container tags are Ultimate-only on GitLab.com/Self-Managed. The mandatory labs therefore require neither Ultimate nor Self-Managed administration, privileged runners, cloud spend, nor a persistent registry credential.

1. The practical problem: “image:latest” is not a release identity

Chapter 22 treated packages as governed distribution objects. Container images are also release artifacts, but OCI adds another layer of indirection: a human-friendly tag points to a manifest, while a content-addressed digest identifies exact manifest bytes. If a deployment records only service:latest, the same text can resolve to different content tomorrow.

This chapter therefore treats the registry as production state. The useful question is not “did we push an image?” but “which project repository owns it, which manifest digest was produced, what source and pipeline created it, who may mutate its tags, what scan evidence belongs to that digest, and what retention rule keeps rollback possible?”

2. Registry object model: project → repository → manifest → tag/digest

Object Meaning Why operators care
GitLab project Authorization, CI/CD, settings, registry ownership boundary. Determines who can publish/delete and which CI identity exists.
Container repository OCI image name beneath the project registry path. Separates services/variants such as api and worker.
Manifest / index OCI descriptor for one platform image or a multi-platform index. Digest identifies exact manifest/index bytes.
Tag Mutable human-readable pointer such as v1.4.0 or latest. Convenient selector, weaker identity unless immutability is enforced.
Digest Content-addressed identifier such as sha256:…. Stable evidence for deployment, rollback, scan association, and provenance.

Layers may be shared across manifests, so repository/tag deletion and physical storage reclamation are not the same operation.

3. Mental model: source and pipeline create a registry object; deployment consumes a digest

OCI identity and trust flow
flowchart TD
  G[Git commit / ref] --> P[Pipeline + build job]
  P -->|CI_REGISTRY_USER + short-lived password| R[Project Container Registry]
  R --> T[Tag: commit-abc123]
  T --> D[Manifest digest sha256:...]
  D --> S[Container scan report]
  D --> E[Deployment / runtime]
  C[Cleanup + protection policy] --> T
  A[Self-Managed storage + GC] --> R

The pipeline publishes into a project-owned registry path. The tag is a name, the digest is the content identity. Scanning and deployments are useful only when they can be tied back to that identity. Cleanup changes tag visibility; Self-Managed garbage collection determines when unreferenced storage is actually reclaimed.

4. OCI identity: tag equality is weaker than digest equality

An OCI reference may be written as registry.example.invalid/group/project/api:v1 or as registry.example.invalid/group/project/api@sha256:<digest>. The first asks the registry what v1 points to at request time. The second names the manifest content directly.

registry.example.invalid/platform/payments/api:v1.4.0
registry.example.invalid/platform/payments/api@sha256:0123456789abcdef...

A platform-specific image can have one digest while a multi-architecture index has another. Record which digest your deployment mechanism resolves and uses; do not compare unrelated manifest and platform-manifest digests as if they were the same object.

5. Authentication is short-lived; authorization is registry-scope plus project permission

Current registry token methods include personal, project, group, and deploy tokens. For token-based access, pull requires read_registry; push requires both read_registry and write_registry. In CI, GitLab exposes CI_REGISTRY_USER and CI_REGISTRY_PASSWORD; the password is job-only, has the same value as CI_JOB_TOKEN, and expires with the job.

Identity Best use Risk / control
CI_REGISTRY_USER + CI_REGISTRY_PASSWORD Publish from the current pipeline. Ephemeral; preferred mandatory lab identity.
Deploy token Long-lived machine pull/push outside CI. Give only read_registry unless publishing is required; expire/revoke.
Project/group/PAT API/human automation where documented. Persistent and often broader; avoid when job identity is sufficient.
Username/password Limited cases without 2FA. Do not build production automation around a reusable account password.

Use --password-stdin; do not place a registry password on a command line, in source, or in a trace artifact.

6. Read-only inspection comes before publish or delete

Prove the project registry is enabled and inspect current repositories before changing anything:

git rev-parse HEAD
glab container-registry repository list --output json
# For a known repository ID:
glab container-registry repository view <repository-id> --include-tags --output json
glab container-registry tag list <repository-id> --details --output json

The current glab container-registry commands operate against GitLab’s registry metadata API. Detailed tag listing adds digest, size, and creation data. Record project, repository ID/path, tag, digest, commit SHA, and pipeline ID together.

7. Cleanup policy removes tags; storage reclamation is a separate layer

GitLab project cleanup policies select tags by name/age and keep rules. Current behavior always keeps latest, excludes configured keep patterns and recent tags, and also excludes protected/immutable tags. Deleting a tag can leave manifest/layer data referenced elsewhere or awaiting garbage collection.

On GitLab.com/Dedicated, the service operates storage reclamation. On Self-Managed, administrators own registry storage and garbage-collection architecture. With the registry metadata database, GitLab supports online garbage collection; legacy/offline modes have different operational procedures. A project Maintainer should not run administrator garbage-collection commands merely because a cleanup policy removed tags.

8. Protection and immutability are different controls

Protected container repositories restrict who may push to matching repository paths and are Free across current offerings. Protected container tags restrict who may push/delete matching tags and are currently documented for GitLab.com/Self-Managed. Immutable container tags prevent matching existing tags from being updated or deleted, but are Ultimate-only on GitLab.com/Self-Managed.

Digest-based deployment remains useful even if a tag is protected or immutable: permission policy controls mutation; digest identity proves which manifest was selected.

9. A scan report is evidence about an image, not proof the image is trusted

Current GitLab container scanning is Free/Premium/Ultimate and uses a GitLab-managed CI template around the Trivy analyzer. The job can emit gl-container-scanning-report.json and a CycloneDX SBOM. Richer vulnerability-management surfaces vary by tier.

A “green scan” does not prove source provenance, absence of malware, correct base-image policy, correct digest selection, or future vulnerability status. Preserve the scanned image reference/digest, analyzer version/evidence, commit, and pipeline so findings cannot be accidentally attached to a different tag incarnation.

10. Production invariant: the release record must survive tag movement

A production handoff should be reconstructible from immutable evidence: source commit → pipeline → image repository → manifest digest → scan/report → deployment. Tags can remain for humans, but deployment/rollback decisions should be verifiable against the digest actually used.

Knowledge check

Why can two deployments both say api:latest yet run different software?

What is the minimum token scope for pushing to the Container Registry?

Does deleting a tag immediately guarantee that all corresponding blobs are physically gone?

Why is an image scan not equivalent to image trust?

What evidence should connect a deployment back to CI?

Summary

The operating model is now explicit: GitLab owns project-level registry authorization, OCI defines repositories/manifests/tags/digests, CI supplies short-lived registry identity, cleanup controls tag retention, and scanning produces security evidence. The digest is the durable content coordinate tying those layers together.

Official references

Primary sources used for the current GitLab 19.3 behavior taught in this lesson:

Next lesson

Guided Hands-On Workflow and Core Operations

Build a disposable evidence chain from preflight inspection through tag/digest comparison, scan evidence, retention simulation, and verified cleanup.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.