Skip to content

Proposal: Easier mechanism for repository updates #575

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
jcarter3 opened this issue May 20, 2025 · 5 comments
Open

Proposal: Easier mechanism for repository updates #575

jcarter3 opened this issue May 20, 2025 · 5 comments

Comments

@jcarter3
Copy link

Many tools exist these days to help users to upgrade their dependencies. A non-exhaustive list includes:

There is no existing API in the distribution spec to check for "new" tags (or manifests) - so if clients want a registry agnostic solution, they need to list all tags and try to find an update by using semvar rules. Since semvar is not universal, this is not an amazing experience. Additionally, this tag listing doesn't indicate if a tag has moved to a different digest, requiring a separate HEAD request to check that.

Because of this, several clients have also implemented registry specific API calls which do allow for querying tags by last updated. These APIs are not always well suited for this task though, and provide far more information and is actually necessary for this update check.

I'd like to start some discussion around ways we can make this easier for both the clients (more efficient checks, universally supported) and registries (lower burden from scrapers). It can also be used to make it easier to mirror repositories across multiple registries. A few initial ideas:

Option 1 - New update endpoint, in the style of catalog (not repo scoped):

/v2/updates?repository=foo/bar&repository=foo/baz&since=<time>
This would return a list of json objects in a format like:

{
    "repository": "foo/bar",
    "digest": <digest>,
    "tag": <tag>, // if present
    "mediaType: <you_get_the_idea>,
    "timestamp":  ...
}

Pro: A single endpoint to get updates to N repositories, though the response would then need sorted out.
Con: Stateless clients may not know a since value to add, which could require it to default to the last N updates per repo, or some default time value.

Option 2 - Improved tag/manifest listing

There are some existing proposals/discussions to improve the tag/manifest listing endpoints to provide more usable data. If we could list tags/manifests using a sort, and the response data coming back included more metadata (timestamps, digests, mediatypes, etc), it could solve this need.
Pro: A more generic solution solving multiple needs
Pro: More options on checking for updates - Updates in , updates pushed since some digest, etc
Con: Need to check each repository individually.

At Docker, we'd like to start pushing hard on this and moving quickly on some implementation and start getting clients to move over, but want input on a preferred direction from other clients and distribution maintainers.

@sudo-bmitch
Copy link
Contributor

Adding to the cons of option 1, some registries are stateless, without a transaction log of changes per repository. Coordinating timestamps in a distributed ecosystem is also problematic (a client may have the wrong time and start requesting a very long history, and apps may not properly handle responses with timestamps in the future).

As an alternative to option 1, I've thought it would be interesting to have a persistent connection to the registry, subscribed to a repository, and receiving updates as they are received. I imagine a few issues with that, including way too many open connections for major registries to support, and a thundering herd problem with the registry notifies all the listeners that a popular base image has been updated.

I'd be a fan of option 2 just knowing how many additional issues an improved tag/manifest listing API would solve. Questions like "what tags point to this digest", "report the differences between two mirrors", and "identify every sigstore-style tag that doesn't have an associated manifest".

One side note, watchtower seems to have been abandoned. So even if we improve the APIs, it's quite likely a large number of users will continue to use the existing APIs until a replacement is created.

@jcarter3
Copy link
Author

We have also thought a bit about an RSS feed, but there are issues with that as well. Option 2 would probably be the best way of solving multiple problems though.

It does seem that watchtower is abandoned, but we've been in contact with many other tool creators and many are aware of the challenges involved and seem willing to work with registries to improve things. Obviously it would take a long while to get everyone to shift some workloads over, but ideally we can offer a big carrot by offering a better experience.

@rchincha
Copy link
Contributor

https://cloudevents.io/

@sajayantony
Copy link
Member

@sozercan who might be interested in this for copacetic as well.

@jcarter3
Copy link
Author

jcarter3 commented May 23, 2025

As discussed on the call, it could be interesting to adopt what gcr.io is doing with the tag listing - returning a manifest field in the JSON response:

{
  "name": "distroless/static",
  "child": [],
  "tags": [
    "00b606183cd65672a152e57d59f6343044745344",
    "0130c4f8f7907bfb031d990c3c0d437ad5cc2952",
    "01579c3dd0f9b4397fe4f50769a9caea130b15e7",
    "02707ab94a0fc952ba542f29b6c7b9252c0a9417",
    "02879de95e16992cac84617e9c7ea0cd8399c910"
    // truncated
  ],
  "manifest": {
    "sha256:00011944270ecdf390fffd52bca48d156af3ffd074ebfcd1d02d61d9a82e89f4": {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "imageSizeBytes": "1520",
      "tag": [],
      "timeCreatedMs": "-6795364578871",
      "timeUploadedMs": "1663934484435"
    },
    "sha256:0014ac288cebb4ea0de8dfa266b5cd8720d39cac6010ac9eb7bceb8efa058fb3": {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "imageSizeBytes": "473",
      "tag": [],
      "timeCreatedMs": "-6795364578871",
      "timeUploadedMs": "1743196123986"
    },
    "sha256:001721750e280012f090a04278f7ea4b749dbfbc41588dde2ec9841c6d2f2bfe": {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "imageSizeBytes": "1147",
      "tag": [
        "sha256-677c99c45273655dcfcfd02ef9d201d6275005d01d3fe55d89b1ab34b5830e2f.sig"
      ],
      "timeCreatedMs": "-6795364578871",
      "timeUploadedMs": "1632188618032"
    }
    // truncated
  }
}

This is already in the wild in a few registries and is backwards compatible.

Assuming semver, clients could call /v2/<name>/tags/list?last=<current_tag>, where <current_tag> is one the user is currently using, and the response include "newer" tags. The manifest field would then include the digest, mediatype, timestamp data that could also be useful. While not a perfect situation, it could at least help with the "are there updates?" question with minimal changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants