Cup: a Rust update checker for Docker images
🥤Docker container updates made easy
At a glance
- What is it?
- Cup is a small Rust binary that checks container images for newer tags and exposes the result through a CLI and a web server. It is built for people who want update data, not automatic redeployment, and the README is explicit about that boundary.
- Who is it for?
- Cup fits operators who run a handful to a few dozen containers and want a fast, low-footprint update report they can read or pipe into their own tooling. It is the wrong choice if you expect the tool to restart containers or fire webhooks on its own; the README says to use What's up Docker for that.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 71 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Cup checks and who it is for
Cup answers one question: is there a newer tag for the images running on this machine? It reads the containers Docker already knows about, queries the registry each image came from, and reports which ones have a newer version available. That is the whole job.
The README frames the motivation around rate limits. The author states that not exhausting registry limits was the original reason for building Cup, and points to Docker Hub reducing pull limits for unauthenticated users. If you have ever run a naive update script that hammers a registry and gets throttled, this is the problem Cup was written to avoid.
The audience is self-hosters and small server operators. The README's own example is a Raspberry Pi 5, where it reports 58 images checked in 3.7 seconds. That number comes from the author's hardware, not from an independent measurement, so treat it as an indication of scale rather than a guarantee.
Cup is not a deployment tool. The README is unusually direct about this: Cup cannot directly trigger your integrations, and it suggests What's up Docker if you want automatic action. Everything downstream of the check is your responsibility.
How Cup talks to registries and to Docker
The dependency list shows the shape of the program. bollard is the Docker API client, so Cup talks to the Docker daemon rather than parsing compose files or image names from disk. reqwest with rustls-tls handles registry requests, and reqwest-retry plus reqwest-middleware sit on top of it, which is consistent with a tool whose stated goal is not to trip rate limits: retries and middleware are how you behave politely when a registry pushes back.
Registry support is broader than Docker Hub. The README lists Docker Hub, ghcr.io, Quay, lscr.io and Gitea or its derivatives. Authentication uses the http-auth crate, so private registries are in scope as long as credentials are configured.
The binary has two modes, gated by Cargo features. The default feature set enables both server and cli. The server feature pulls in xitca-web for HTTP, liquid for templating, chrono for time handling and tokio-cron-scheduler for periodic checks. The cli feature pulls in indicatif and termsize, which are progress bars and terminal width detection. If you build with --no-default-features and select only cli, you get a much smaller dependency tree and no web server.
The release profile is tuned for size rather than speed of compilation: opt-level is set to "z", symbols are stripped, panic is set to abort, LTO is fat and codegen-units is 1. That combination explains the README's claim that the binary is 5.4 MB at the time of writing. It also means release builds are slow, which matters if you compile it yourself.
The web interface is a separate Bun-built frontend. The Dockerfile builds the web directory with oven/bun:1-alpine, copies the resulting dist into src/static, and then the Rust build embeds it. The final image is FROM scratch, containing only the binary, and exposes port 8000. There is no shell in that image, which is worth knowing before you try to exec into it.
Installing Cup and running a first check
The README points to https://cup.sergi0g.dev/docs for installation instructions rather than listing them inline, so the canonical steps live there. What the repository does show is that the package is named cup in Cargo.toml, and that a Dockerfile exists that produces a scratch-based image exposing port 8000.
The Dockerfile itself shows the build order. It installs frontend dependencies with bun and builds the web directory before the Rust stage runs, because src/static is populated from that output:
WORKDIR /web
COPY ./web/package.json ./web/bun.lock ./
RUN bun install
COPY ./web .
RUN bun run buildAfter the frontend exists, the Rust stage builds the binary. The Dockerfile runs cargo build --release in the /cup working directory.
WORKDIR /cup
COPY Cargo.toml .
COPY Cargo.lock .
COPY ./src ./src
RUN cargo build --releaseThe README gives one concrete invocation for retrieving results: running cup check -r. The -r flag is the form shown in the README's own example of how to retrieve data periodically, for instance from a cronjob.
cup check -rIf you run the server instead, the Dockerfile exposes port 8000, and the README refers to the /api/v3/json endpoint as the way to pull results programmatically. That endpoint is the integration surface: point a script or dashboard at it and parse the JSON.
The integration gap is deliberate, and it is the main limitation
Cup stops at reporting. The README states outright that Cup cannot directly trigger your integrations, and that if you want automatic action you should use What's up Docker instead. This is not an oversight being apologized for; the author describes Cup as having been created to be simple, with the data left for you to retrieve.
That design has a real cost. A container with an available update will sit there until something else acts on it. You need a cronjob running cup check -r, or a scheduled request to /api/v3/json, plus whatever logic turns that JSON into a pull and a restart. If your environment expects the checker to be the whole update pipeline, Cup is the wrong tool and the README says so.
The second limitation is scope. The README describes Cup as a work in progress that might not have as many features as alternatives, and asks users who need a missing feature to consider another tool. Feature parity with more mature update tools is explicitly not claimed.
A third constraint is implicit in the architecture: because Cup uses bollard to talk to the Docker daemon, it needs access to that socket. The README does not document the socket permissions or the security implications of mounting it, so that is something to work out from your own deployment model rather than from the project's documentation.
Cup compared with What's up Docker
The README names What's up Docker twice: once in the acknowledgements as the project that inspired Cup, and once in the limitations section as the recommended alternative when you need automatic triggering. That is an unusually honest pointer, and it makes the comparison easy to state.
What's up Docker is built around acting on updates. Cup is built around reporting them. If your requirement is that a new image tag results in a container being recreated without you writing the glue, the difference is not one of degree; Cup simply does not do that part, and the README directs you elsewhere.
The trade-off Cup offers in exchange is footprint and speed. The README contrasts Cup's 5.4 MB binary with pulling 100+ MB Docker images for what it calls a simple program, and the release profile in Cargo.toml is tuned for exactly that outcome. If you are running on a Raspberry Pi or another constrained host, that difference is the reason to pick Cup.
The README also notes that Cup was created to avoid exhausting registry rate limits, which it presents as especially relevant given Docker Hub's reduced pull limits for unauthenticated users. If registry throttling is what pushed you to look for a checker in the first place, that is the design goal Cup was written around.
Licence, maintenance and what upgrading costs you
Cup is licensed AGPL-3.0. If you run the server component and expose it to users over a network, the AGPL's network-use clause is the part that deserves your attention, because it can extend source-availability obligations to modified versions you make available to others. That is a general property of the licence, not legal advice, and if you plan to modify and host Cup for others you should get proper advice rather than relying on a summary.
The repository is not archived, and the last push was on 2026-07-22. The most recent tagged release listed is v3.5.1 from 2025-11-21, with v3.5.0 the day before, and a nightly build from 2025-03-25. The version in Cargo.toml matches v3.5.1, so the released artifact and the manifest are in step.
Upgrade cost is low if you use the binary. It is a single static executable in a scratch image with no shell and no runtime dependencies to reconcile. If you build from source, budget for the release profile: opt-level "z" with fat LTO and codegen-units 1 trades compile time for binary size, and you also need Bun available to build the frontend before Cargo can embed it. The README directs contributors to the docs for more detail, and the repository carries CONTRIBUTING.md if you intend to patch it.
Editorial conclusion
Cup fits operators who run a handful to a few dozen containers and want a fast, low-footprint update report they can read or pipe into their own tooling. It is the wrong choice if you expect the tool to restart containers or fire webhooks on its own; the README says to use What's up Docker for that. Before adopting it, check the docs at cup.sergi0g.dev/docs for the registry authentication options, confirm which of your registries are supported, and decide how you will consume the JSON output, since nothing is wired up for you.
Frequently asked questions
Does Cup update my containers automatically?
No. The README states that Cup cannot directly trigger your integrations and suggests What's up Docker if you want that to happen automatically. Cup produces the update data, and retrieving it is left to you, for example by running cup check -r from a cronjob or requesting /api/v3/json.
Which container registries does Cup support?
The README lists Docker Hub, ghcr.io, Quay, lscr.io and Gitea or its derivatives. Authentication is handled through the http-auth dependency, so private registries are in scope once credentials are configured.
How do I install Cup?
The README points to https://cup.sergi0g.dev/docs for installation rather than listing steps inline. The repository also contains a Dockerfile that builds the binary into a scratch image exposing port 8000, and Cargo.toml defines the package as cup for a source build.
Can Cup produce JSON output for a dashboard or webhook?
Yes. The README lists JSON output for both the CLI and the web interface as a feature, describing it as easy to parse for webhooks and dashboards. The server exposes results at /api/v3/json.
What licence is Cup released under?
Cup is licensed AGPL-3.0, as shown by the LICENSE file and the repository metadata. The network-use clause is the part to review if you intend to host a modified version for other users.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/sergi0g-cup)