Self-hosted service
klausmeyer/docker-registry-browser avatar
klausmeyer/docker-registry-browser

docker-registry-browser: a web interface for the Docker Registry V2 API

🐳 Web Interface for the Docker Registry HTTP API V2 written in Ruby on Rails.

701 stars64 forksRubyMIT

At a glance

What is it?
Docker Registry Browser is a Ruby on Rails application that puts a web interface in front of the registry HTTP API, so you can browse repositories and tags and delete the images you pushed without writing curl commands against a JSON endpoint. It is small, MIT licensed and actively released, and the parts worth understanding are the security settings it exposes and the production container it ships.
Who is it for?
Adopt Docker Registry Browser if you run a private registry and want a human way to see what is in it, since the registry API is usable from a terminal but not pleasant, and this gives you a browsable table instead. Do not expose it to a network you do not control, because the delete feature is a real write operation against your images and the tool is designed to sit behind your own boundary.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What it does, and the four screens the README illustrates

Docker Registry Browser is a web interface for the Docker Registry HTTP API V2, written in Ruby on Rails, and the repository description calls it exactly that.

That framing matters. It is not a registry implementation and it does not store images. It is a front end for an existing registry, talking the standard V2 API, which means it works with the reference registry image and with anything else that implements the same API.

The screenshots in the guide show the four screens, and together they describe the feature set. There is a repositories overview, a tag overview for a single repository, tag details, and a delete tag action.

That last one is the feature that decides whether you want this tool. Deleting a tag is a write operation against the registry, and most people who run a registry have wanted to clean up an old tag and found the API awkward enough to avoid doing it. A browser view with a delete action is the difference between the tag pile growing forever and it not.

The delete is not a default, though, and the configuration makes that explicit. The application is available as open source under the terms of the MIT License, and the usage section is a single docker run:

shell
$ docker run --name registry-browser -e SECRET_KEY_BASE="..." -p 8080:8080 klausmeyer/docker-registry-browser

The note on the secret is a real one, because the value can be generated with openssl rand -hex 64. That is a Rails convention, since SECRET_KEY_BASE signs the session and cookie data, and a fixed or shipped value means anyone who has read the compose file can forge a session for your instance.

The compose file, and the two settings that decide how dangerous this is

The docker-compose.yml in the repository is short and it is worth reading in full, because it configures both halves of the system.

The backend is the reference registry, image registry:2, with REGISTRY_HTTP_ADDR set to 0.0.0.0:5555 and REGISTRY_STORAGE_DELETE_ENABLED set to true. So the registry itself is running with deletion enabled, which the storage backend refuses unless you ask for it.

The frontend is built from the local directory and gets four environment variables. DOCKER_REGISTRY_URL points at the backend service. PUBLIC_REGISTRY_URL is localhost:5555, which is what gets shown to the user as the address of the registry. ENABLE_DELETE_IMAGES is set to true, and that is the switch that turns on the delete action in the interface. And SECRET_KEY_BASE is set to a literal hex string, which is the value a developer would obviously replace.

So the two switches that matter are ENABLE_DELETE_IMAGES in the frontend and REGISTRY_STORAGE_DELETE_ENABLED in the backend. The first decides whether the interface offers the delete button. The second decides whether the registry honours a delete request. Both have to be on for the feature to work, and both default to off in the underlying registry, which is a sensible arrangement for a tool whose most dangerous action is a single click.

The compose file also publishes 8080 for the frontend and 5555 for the registry, both on the host, and the frontend talks to the backend over the compose network by service name rather than through the host, which is the detail that makes the two-service setup work without extra configuration.

It is worth noting what this compose file is not. It is a development and demonstration arrangement, with a plaintext registry, a published port and a hardcoded secret, and it should not be copied into production as-is.

The production Dockerfile, and the two details that show real deployment experience

The Dockerfile in the repository is for production, and its own comment says so. It is designed to be used with Kamal or built and run by hand, and the example command shows the shape of that, running the image with the RAILS_MASTER_KEY passed in from config/master.key.

The base image is the official Ruby slim image with a version argument, and there is a comment that the Ruby version must match the version in the .ruby-version file, which is at the repository root along with a .ruby-gemset. The repository carries both, so a mismatch between the image and the expected interpreter is the kind of thing that is caught by a comment rather than by a build failure.

The build stage is a throw-away one, and the first thing it does is install build-essential, git, libyaml-dev and pkg-config, which are the packages needed to compile native gems. The application gems are installed from the vendored directory, with the Gemfile and Gemfile.lock copied in, and then the .bundle and the git directories and the cache directories are removed so the final image does not carry the history of the bundle.

The first of those two details is the interesting one. The bundle install step carries a comment that -j 1 disables parallel compilation to avoid a QEMU bug, with a link to the bootsnap issue. That is a workaround for a specific bug in emulation, and it only appears in a Dockerfile when somebody has hit it and written down what happened. It also has a performance cost, since gem compilation is now serial, so the comment is there so that a future maintainer does not remove the flag and reintroduce the failure.

The runtime base installs curl and libjemalloc2, and the jemalloc library is symlinked into place so it can be preloaded. The environment sets RAILS_ENV to production, BUNDLE_DEPLOYMENT to 1, BUNDLE_PATH to a fixed location, BUNDLE_WITHOUT to development, and LD_PRELOAD to the jemalloc library, with the comment that this is for reduced memory usage and latency.

So the container is a real production image, not a convenience wrapper, and the deploy story assumes you have a Rails deployment story.

The Rails project layout, and what it tells you about the test setup

The repository root is a conventional Rails application, and the top level list tells you which parts of the Rails ecosystem this project uses.

There is app/ for the application code, config/ for the Rails configuration, db/ for the database layer, lib/ for the library code, bin/ for the binstubs, and a config.ru for the Rack entry point. There are public/ for static assets, spec/ for the tests, log/ and tmp/ for the usual Rails directories, and vendor/ for vendored gems, which the Dockerfile copies into the build stage.

The test setup is RSpec, which is clear from the .rspec file and the spec/ directory, and the linting is RuboCop with a .rubocop.yml. There is a Rakefile for the standard Rails tasks and a CHANGELOG.md at the root, and a Dockerfile, a .dockerignore and a .gitattributes alongside it.

The presence of vendor/ in the top level list and the Dockerfile copying vendor/* into the build stage is a decision about how gems are shipped. Vendoring means the build is reproducible and the image does not depend on what a gem server is serving that day, at the cost of a large repository and a manual process for updating dependencies.

The docs/ directory is where the real documentation lives. The README itself defers to it, saying to have a look at the documentation for more details and available configuration options, and the configuration options are the part that matters here, because the interesting settings in this project are the ones that control what the interface is allowed to do to your registry.

Maintenance, licensing, and the questions to answer before you point it at production

The maintenance picture is healthy for a small project. v1.10.1 was published on 2026-09-23, v1.10.0 on 2026-07-20 and v1.9.2 on 2026-04-05, and the last push to the repository was on 2026-10-18 with the repository not archived. So this is actively worked on rather than a project that reached a feature and stopped.

The licence is the MIT License, stated in the README and with a LICENSE file at the repository root, which is the least restrictive of the common choices and the one you want in a tool that sits in front of your infrastructure.

The project is also published as a Docker image on Docker Hub under the klausmeyer organisation, with the badge in the README pointing at the repository page, and the image is the install path the guide documents. There is a Discord link and a Gitter room badge in the CI row, and an issue tracker on GitHub.

The questions to answer before you point it at a real registry are all about the boundary. The tool performs deletes against your images, so the first question is whether you want ENABLE_DELETE_IMAGES on at all, given that a mistake there is not recoverable. The second is where the instance is reachable from, since the interface has full write access to whatever registry it can see, and the compose file publishes the registry port on the host. The third is authentication, because the registry itself has no authentication configured in that compose file, and the browser application is the only thing standing between the internet and a delete endpoint.

The fourth is the secret, and it is the one the guide helpfully gives you the command for, openssl rand -hex 64. The sample value in the compose file is a value that has been published in a public repository, so it must not survive into a deployment.

Editorial conclusion

Adopt Docker Registry Browser if you run a private registry and want a human way to see what is in it, since the registry API is usable from a terminal but not pleasant, and this gives you a browsable table instead. Do not expose it to a network you do not control, because the delete feature is a real write operation against your images and the tool is designed to sit behind your own boundary. Before you deploy it, decide about ENABLE_DELETE_IMAGES, and generate SECRET_KEY_BASE with openssl rand -hex 64 rather than shipping the sample value that appears in the compose file.

Frequently asked questions

What does the Docker Registry Browser application do?

It is a Ruby on Rails web interface for the Docker Registry HTTP API V2, giving you a repositories overview, a tag overview per repository, tag details and a delete tag action, so you can browse and clean up a registry without writing curl commands against a JSON endpoint.

How do I run the Docker Registry Browser?

With docker run --name registry-browser -e SECRET_KEY_BASE="..." -p 8080:8080 klausmeyer/docker-registry-browser. The value for SECRET_KEY_BASE can be generated with openssl rand -hex 64, and the docker-compose.yml in the repository also wires it to a registry:2 backend.

How is deletion of images enabled?

Two settings have to be on. ENABLE_DELETE_IMAGES in the frontend enables the delete action in the interface, and REGISTRY_STORAGE_DELETE_ENABLED in the registry allows the storage backend to honour the request. Both are set to true in the repository's compose file, and both default to off in the underlying registry.

Is the Docker Registry Browser image meant for production?

Yes. The Dockerfile says it is designed for production, not development, and is meant to be used with Kamal or built and run by hand, with the RAILS_MASTER_KEY passed in from config/master.key. It uses a throw-away build stage, vendors the gems, and preloads jemalloc for lower memory usage and latency.

Official sources

  1. klausmeyer/docker-registry-browser on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/klausmeyer-docker-registry-browser.svg)](https://hysenlabs.com/projects/klausmeyer-docker-registry-browser)

Was this useful?