Skip to main content

Delete old images with registry retention policies

A retention policy deletes old images from a project automatically, so CI builds and stale versions don't fill your storage. You write rules that say which images to keep; when the policy runs, every other image in the repositories the rules cover is deleted. Run it by hand, on a schedule, or as a dry run that only reports what it would delete.

At a glance​

WhereA project's Policy tab, Tag Retention section. Also the CLI, API and MCP
Rules per projectUp to 15
What a rule keepsThe N most recently pushed or pulled images, images pushed or pulled in the last N days, or every image
Which images a rule looks atRepositories and tags chosen with patterns (**, api, team/*, v*), matching or excluding
ScheduleNever (by hand only), hourly, daily or weekly, in UTC
Dry runReports what would be deleted, deletes nothing
ProtectedTags an immutability rule covers are never deleted
Not availableIn the apps project, which Cloider prunes itself

How retention works​

When the policy runs, Cloider looks at each repository in the project:

  1. A repository that no rule covers is left alone.
  2. In a repository that some rule covers, each rule picks the images whose tags match its tag patterns, and keeps some of them according to its Keep setting.
  3. Every image that no rule keeps is deleted. Each rule is worked out on its own, and an image that any rule keeps stays.
  4. An image whose tag is protected by an immutability rule is always kept (reported as Kept, immutable).

Untagged images are only seen by rules that have Untagged images too turned on. Untagged images in a covered repository that no rule keeps are deleted.

Retention deletes what isn't kept

A rule says what to keep, not what to delete. A single rule such as "in repositories **, keep the 5 most recently pushed images with tags sha-*" deletes every image in every repository that doesn't have a sha-* tag among the 5 newest, including release images tagged 1.0. Add a second rule that keeps the rest (for example tags excluding sha-*, keep Every image), and always start with a Dry run.

What a rule can keep​

Keep (dashboard)keep valuecount meansRange
The most recently pushedlatest_pushedNumber of images1 to 10000
The most recently pulledlatest_pulledNumber of images1 to 10000
Pushed within the lastpushed_within_daysDays1 to 3650
Pulled within the lastpulled_within_daysDays1 to 3650
Every imagealwaysNot used

Patterns​

Each rule has a repositories selector and a tags selector. A selector is either matching (the patterns pick what the rule covers) or excluding (the rule covers everything the patterns don't match), with up to 20 patterns.

PatternMatches
**Everything (the default)
apiExactly api
team/*team/api, team/web, but not team/a/b (* stays within one path segment)
team/**Everything under team/, at any depth (** crosses segments)
v*v1, v1.2.0, v2-rc1
1.?1.0 to 1.9
sha-*sha-4f2a9c1
[0-9]*Tags that start with a digit, such as 1.4.0

Repository patterns use lowercase letters, digits, ., _, -, / and the wildcards *, **, ? (and [...] character classes). Tag patterns use letters, digits, ., _, - and *, ? (and [...]). In the dashboard, separate several patterns with commas.

Add retention rules​

  1. Open the project and go to the Policy tab.
  2. In Tag Retention, click Add rule.
  3. For the repositories: choose matching or excluding and enter patterns, for example ** for all repositories.
  4. Keep: choose what to keep, for example The most recently pushed and 10 images.
  5. Tags: choose matching or excluding and enter patterns, for example **.
  6. Tick Untagged images too if untagged images should count as matching the tags, so the rule can keep them. Unkept untagged images are deleted.
  7. Click Add rule.

The rule appears in the list as a sentence, for example In repositories matching **, keep the 10 most recently pushed images with tags matching **, untagged images included. Each rule has an Enabled switch, and edit and delete buttons.

The acme project's Policy tab with Tag Retention rules, the schedule, Retention Runs and Tag Immutability rules
The Policy tab: retention rules and schedule, the run history, and immutability rules.

Example rule sets​

Keep the last 10 images of every repository​

[{"keep": "latest_pushed", "count": 10, "untagged": true}]

CI builds: keep 20 commit builds, every release​

Commit builds are tagged sha-*; everything else (versions, latest) is kept.

[
{"tags": {"match": "matching", "patterns": ["sha-*"]},
"keep": "latest_pushed", "count": 20, "untagged": true},
{"tags": {"match": "excluding", "patterns": ["sha-*"]},
"keep": "always"}
]

Delete images nobody pulled in 90 days, except releases​

[
{"tags": {"match": "matching", "patterns": ["**"]},
"keep": "pulled_within_days", "count": 90},
{"tags": {"match": "matching", "patterns": ["v*", "[0-9]*"]},
"keep": "always"}
]

Clean only one group of repositories​

Repositories outside team-a/** aren't covered by any rule, so they are left alone.

[
{"repositories": {"match": "matching", "patterns": ["team-a/**"]},
"keep": "pushed_within_days", "count": 30, "untagged": true}
]

Keep the last 5 images per environment tag family​

[
{"tags": {"match": "matching", "patterns": ["staging-*"]}, "keep": "latest_pushed", "count": 5},
{"tags": {"match": "matching", "patterns": ["production-*"]}, "keep": "latest_pushed", "count": 10},
{"tags": {"match": "excluding", "patterns": ["staging-*", "production-*"]}, "keep": "always"}
]

Enable, disable, edit and delete rules​

  • Enabled switch: a disabled rule stays in the list but doesn't apply. In JSON, "disabled": true. A policy with no enabled rule can't run.
  • Edit (pencil) opens Edit Tag Retention Rule; click Save rule.
  • Delete (trash) asks Delete this retention rule? Images only it kept are deleted the next time the policy runs.

With the CLI and API, edit the JSON and set it again: the list you send replaces the rules.

Schedule the policy​

A schedule runs the policy on its own. Times are in UTC; the dashboard also shows your local time. The most frequent schedule is hourly.

  1. In the Policy tab, under the rules, find Schedule.
  2. Choose Never, Hourly (at minute), Daily (at hour : minute) or Weekly (on a weekday, at hour : minute).
  3. Click Save.

A schedule set by support shows as Custom with its cron expression.

Run the policy now, or as a dry run​

A dry run goes through the same steps as a real run and reports what it would delete, without deleting anything. Do one after every change to the rules.

  1. In the Policy tab, in Tag Retention, click Dry run (shows what a run would delete, without deleting anything).
  2. Watch the run in Retention Runs below; the list refreshes on its own while a run is pending or running.
  3. When it looks right, click Run now and confirm in Run Retention Policy: images no rule keeps are permanently deleted.

Both buttons are disabled while there is no enabled rule or while a run is in progress.

Read the results of a run​

Each run is listed with its Started time, Trigger (Manual or Scheduled), Status and Duration, and a Dry run tag for dry runs. Open a run to see one line per repository with how many images it Kept (Would keep for a dry run) out of the total, then click Images to see every image's result.

Run and task statusMeaning
PendingWaiting to start
RunningIn progress
SucceededFinished
FailedFinished with errors. Open the run to see which repository failed
StoppedStopped before it finished
Image resultMeaning
KeptA rule keeps it
Deleted (Would delete in a dry run)No rule keeps it
Kept, immutableAn immutability rule protects one of its tags
FailedDeleting it failed

In the Policy tab, scroll to Retention Runs. Click a run to expand it, and Images on a repository line to see the per-image results. The policy hasn't run yet. means there are no runs.

Retention and storage​

Deleted images free storage in the project, which lowers its stored size and your bill (see Usage and billing). Images left without a tag in a repository no rule covers are still removed by the nightly cleanup.

Who can change retention?​

Owners and Admins can change rules and schedules and start runs. Members with the Restricted role, and read-only API tokens, can view the policy and its runs. The apps project has no Policy tab: This project holds your apps' images and is managed by Cloider, its policies can't be changed.

Troubleshooting​

ErrorCause and fix
Add a retention rule, or enable one, to run the policy.There is no enabled rule
The policy is already running, wait for it to finish.Only one run at a time. Wait for it in Retention Runs
A policy holds at most 15 rules.Combine rules with several patterns each
Two of the rules are the same, change or delete one of them.Two rules are identical
Keep between 1 and 10000 images / Enter between 1 and 3650 dayscount is out of range for the chosen Keep
Choose what the rule keepskeep is missing or not one of the five values
Choose matching or excludingA selector's match is missing (API)
Enter at least one pattern, ** for all / Enter at most 20 patternsFix the pattern list
"..." isn't a valid pattern.The pattern has a character that isn't allowed, such as an uppercase letter in a repository pattern
Choose how often the policy runs / Choose a valid timeSchedule values out of range
This project's policies were changed outside the dashboard, contact support to edit them.The policy uses a form the dashboard can't show. Contact support
The registry refused the policy, check its rules and try again.The registry rejected a rule. Simplify the patterns
A run deleted more than expectedThe rules keep less than you thought: images that no rule keeps are deleted. Use Dry run before every change, and add a rule that keeps Every image for tags you never want deleted, or protect them with immutability rules

Deleted images can't be recovered. Push them again from your CI or local copies if needed.

Next steps​