The simplest and most complete UI for your private docker registry v2 and v3
Docker Registry User Interface
Overview
This project aims to provide a simple and complete user interface for your private docker registry. You can customize the interface with various options. The major option is SINGLE_REGISTRY which allows you to disable the dynamic selection of docker registries (same behavior as the old static tag).
You may need the migration guide from 1.x to 2.x or the 1.x readme. The project support both docker registry v2 and docker registry v3.
This web user interface uses Riot the react-like user interface micro-library and riot-mui components.
If you like my work and want to support it, don't hesitate to sponsor me.
Supported Docker tags
latest: image with the latest release of Docker Registry UI based onnginx:alpinelatest-debian: image with the latest release of Docker Registry UI based onnginx:debianmain,master: image with the beta version of Docker Registry UI based onnginx:alpinemain-debian,master-debian: image with the beta version of Docker Registry UI based onnginx:debian2: image with the latest release of Docker Registry UI v2 (includes latest minor and patch version)2.x: image with the latest release of Docker Registry UI v2.x (includes latest patch version)2.x.y: image with the specific release of Docker Registry UI v2.x.y
Project Page, Live Demo, Examples, Helm Chart

Hidden Features
- Many ways to delete multiple images at once
ALT + Click on the indeterminate checkbox (see #80 and #81). Since 1.2.1
- Select all contigous tags between two tags with Shift + Click on the first tag then Shift + Click on the second tag (see #287). Since 2.4.0
- Show sha256 for specific tag (hover image tag).
- Sort the tag list with number compatibility (see #45 and #46). Since 0.4.0
- Share your docker registry UI without installation or when you are deploying a UI with
SINGLE_REGISTRY=false.
url (e.g. https://joxit.dev/docker-registry-ui/demo?url=https://registry.example.com). If you need credentials on your private registry, you must set the Access-Control-Allow-Origin to https://joxit.dev.
- You can use a single interface with many registry, add them in the menu in the top right of the page.
- Filter images and tags with the search bar.
CRTL + F or F3. When the search bar is already focused, the shortcut will fallback to the default behavior (see #213). Since 2.1.0
- Multi arch support in history page (see #130 and #134). Since 1.5.0
- Show the content of the dockerfile (see #286). Since 2.4.0
- The UI will cache requests from your registry, such as blobs and some manifests (URL with
sha256:).
FAQ
- What is the difference between
SINGLEREGISTRY=falseandSINGLEREGISTRY=trueoptions ?
SINGLE_REGISTRY is set to false, a menu appears on the interface allowing you to dynamically change docker registry URLs.
- Why, when I delete all tags of an image, the image is still in the UI ?
- Why the image size in the UI is not the same as displayed during
docker images?
- Can I use HTTPS on the UI ?
- Does the UI support authentication ?
- Can I use the UI and docker client with an insecure registry (registry url without https) ?
- What does Mixed Content error mean ?
- Why the default nginx
Hostis set to$http_host?
- Why OPTIONS (aka preflight requests) and DELETE fails with 401 status code (using Basic Auth) or why the UI says to check my
Access-Control-Allow-Origin?
NGINXPROXYPASSURL or configure a nginx/apache/haproxy in front of your registry that returns 200 on each OPTIONS requests. (see #104, #204, #207, #214, #266, #278).
- Can I use the docker registry ui as a standalone application (with Electron) ?
- I deleted images through the UI, but they are still present on the server. How can I delete them?
registry garbage-collect config.yml or docker exec registry registry garbage-collect config.yml. (see #77, #147)
- Why when I delete one tag, all tags with the same SHA are deleted ?
name and its manifest (it's a sha of the content). So when you delete a tag, this will delete all tags of this image with the same SHA/manifest.
- Can I run the container with an unprivileged user ?
nginx user with the option --user nginx, this will also update the listen port to 8080 (see #224 and #234).
- Can I use the UI with a docker hub mirror and show
library/*images ?
- How to fix CORS issue on s3 bucket ?
- Why my docker registry server is returning an error
pagination number invalid?
REGISTRYCATALOGMAXENTRIES with your max value and check the issue #306.
- I'm using
NGINXPROXYPASS_URL, my registry server has been recreated and the UI cannot connect with the message[error] 176#176: *2 connect() failed (111: Connection refused) while connecting to upstream, what can I do?
NGINX_RESOLVER and set to 127.0.0.11.
Need more informations ? Try my examples or open an issue.
Available options
You can run the container with the unprivileged user nginx, see the discussion #224.
Some env options are available for use this interface for only one server (when SINGLE_REGISTRY=true).
REGISTRY_URL: The default url of your docker registry. You may need CORS configuration on your registry. This is usually the domain name or IP of your registry reachable by your computer (e.ghttp://registry.example.com). (default: derived from the hostname of your UI).REGISTRYTITLE: Set a custom title for your user interface. (default: value derived fromREGISTRYURL) (see #28 and #32). Since 0.3.4PULLURL: Set a custom url when you copy thedocker pullcommand (see #71). (default: value derived fromREGISTRY_URL). Since 1.1.0DELETE_IMAGES: Set if we can delete images from the UI. (default:false)SHOWCONTENTDIGEST: Show/Hide content digest in docker tag list (see #126 and #131). (default:false). Since 1.4.9CATALOGELEMENTSLIMIT: Limit the number of elements in the catalog page (see #39, #127, #132) and #306. (default:1000). Since 1.4.9SINGLE_REGISTRY: Remove the menu that show the dialogs to add, remove and change the endpoint of your docker registry. (default:false). Since 2.0.0NGINXPROXYPASSURL: Update the default Nginx configuration and set the proxypass to your backend docker registry (this avoid CORS configuration). This is usually the name of your registry container in the formhttp://registry:5000. Since 2.0.0NGINXPROXYHEADER*: Update the default Nginx configuration and set custom headers for your backend docker registry via environment variable and file (/etc/nginx/.env). Only whenNGINXPROXYPASSURLis used (see #89). Since 1.2.3NGINXPROXYPASSHEADER*: Update the default Nginx configuration and forward custom headers to your backend docker registry via environment variable and file (/etc/nginx/.env). Only whenNGINXPROXYPASSURLis used (see #206). Since 2.1.0NGINXLISTENPORT: Listen on a port other than 80, you can also change the default user and set to nginx--user nginx(see #224 and #234). (default:80when the user is root,8080otherwise). Since 2.2.0NGINXRESOLVER: Addresolverdirective to the nginx configuration for dynamic dns resolving. The value when you are using a docker network is127.0.0.11, you can set a custom DNS server too with a valid time. This is not needed when you are using kubernetes. (see #333 and #339). (default: `). Since 2.5.5- DEFAULTREGISTRIES
: List of comma separated registry URLs (e.ghttp://registry.example.com,http://registry:5000), available only whenSINGLEREGISTRY=false(see #219). (default:). Since 2.1.0 - READONLYREGISTRIES
: Deactivate dialog for remove and add new registries, available only whenSINGLEREGISTRY=false(see #219). (default:false). Since 2.1.0 - SHOWCATALOGNBTAGS
: Show number of tags per images on catalog page and hide images with 0 tags. This will produce + nb images requests, not recommended on large registries (see #161 and #239). (default:false). Since 2.2.0 - HISTORYCUSTOMLABELS
: Expose custom labels in history page, custom labels will be processed like maintainer label (see #160 and #240). Since 2.2.0 - USECONTROLCACHEHEADER
: UseControl-Cacheheader and set tono-store, no-cache. This will avoid some issues on multi-arch images (see #260 and #265). This option requires registry configuration:Access-Control-Allow-HeaderswithCache-Control. (default:false). Since 2.3.0 - THEME
: Chose your default theme, could bedark,lightorauto(see #283). When auto is selected, you will have a switch to manually change from light to dark and vice-versa (see #291). (default:auto). Since 2.4.0 - THEME*
: See table in Theme options section (see #283). Since 2.4.0 - TAGLISTORDER
: Set the default order for the taglist page, could benum-asc;alpha-asc,num-desc;alpha-asc,num-asc;alpha-desc,num-desc;alpha-desc,alpha-asc;num-asc,alpha-asc;num-desc,alpha-desc;num-ascoralpha-desc;num-desc(see #307). (default:alpha-asc;num-desc). Since 2.5.0 - CATALOGDEFAULTEXPANDED
: Expand by default all repositories in catalog (see #302). (default:false). Since 2.5.0 - CATALOGMINBRANCHES
: Set the minimum repository/namespace to expand (e.g.joxit/docker-registry-uijoxit/is the repository/namespace). Branching can be disabled if min and max are set to 0. (see #319). (default:1). Since 2.5.0 - CATALOGMAXBRANCHES
: Set the maximum repository/namespace to expand (e.g.joxit/docker-registry-uijoxit/is the repository/namespace). Branching can be disabled if min and max are set to 0. (see #319). (default:1). Since 2.5.0 - TAGLISTPAGESIZE
: Set the number of tags to display in one page. (default:100). Since 2.5.0 - REGISTRY_SECURED
: By default, the UI will check on every requests if your registry is secured or not (you will see401responses in your console). Set totrueif your registry uses Basic Authentication and divide by two the number of call to your registry. (defaultfalse). Since 2.5.0 - SHOWTAGHISTORY
: Whether to show the tag history feature or not. Allows to simplify the user interface by hiding it form the tag list if set tofalse. (default:true).
- DOCKERREGISTRYUI_TITLE
: Set a custom title displayed in the header bar. (default:Docker Registry UI). - ENABLEVERSIONNOTIFICATION
: Display notification when a new version of Docker Registry UI is available. This is a weekly check. (default:true).
Theme options
This featureswas added to version 2.4.0. See more about this in #283.
| Environment variable | light theme value | dark theme value | | --- | --- | --- | | THEMEPRIMARYTEXT | #25313b | #98a8bd | | THEMENEUTRALTEXT | #777777 | #6d7fab | | THEME_BACKGROUND | #ffffff | #22272e | | THEMEHOVERBACKGROUND | #eeeeee | #343a4b | | THEMEACCENTTEXT | #5f7796 | #5c88ff | | THEMEHEADERTEXT | #ffffff | #ffffff | | THEMEHEADERACCENT_TEXT | #7b9ac2 | #7ea1ff | | THEMEHEADERBACKGROUND | #25313b | #333a45 | | THEMEFOOTERTEXT | #ffffff | #ffffff | | THEMEFOOTERNEUTRAL_TEXT | #adbacd | #98afcf | | THEMEFOOTERBACKGROUND | #344251 | #344251 |
Recommended Docker Registry Usage
Here is a simple usage of Docker Registry UI with Docker Registry Server using docker-compose. This example should work for most of your use case and your UI will be on the same domain as you registry.
<pre><code class="lang-yml">version: '3.8'
services: registry-ui: image: joxit/docker-registry-ui:main restart: always ports: - 80:80 environment: - SINGLE_REGISTRY=true - REGISTRY_TITLE=Docker Registry UI - DELETE_IMAGES=true - SHOWCONTENTDIGEST=true - NGINXPROXYPASS_URL=http://registry-server:5000 - SHOWCATALOGNB_TAGS=true - CATALOGMINBRANCHES=1 - CATALOGMAXBRANCHES=1 - TAGLISTPAGESIZE=100 - REGISTRY_SECURED=false - CATALOGELEMENTSLIMIT=1000 container_name: registry-ui
registry-server: image: registry:2.8.2 restart: always environment: REGISTRYHTTPHEADERS_Access-Control-Allow-Origin: '[http://registry-ui.example.com]' REGISTRYHTTPHEADERS_Access-Control-Allow-Methods: '[HEAD,GET,OPTIONS,DELETE]' REGISTRYHTTPHEADERS_Access-Control-Allow-Credentials: '[true]' REGISTRYHTTPHEADERS_Access-Control-Allow-Headers: '[Authorization,Accept,Cache-Control]' REGISTRYHTTPHEADERS_Access-Control-Expose-Headers: '[Docker-Content-Digest]' REGISTRYSTORAGEDELETE_ENABLED: 'true' volumes: - ./registry/data:/var/lib/registry container_name: registry-server</code></pre>
Using CORS
:warning: Before posting issues about CORS, please read the and all created issues.
:warning: If you are using credentials and your registry is on a different host than your UI, please read the FAQ about OPTIONS), all the linked issues and distribution/distribution#4458 first. The best way for the UI to work is using NGINXPROXYPASS_URL or configure your own proxy (nginx, haproxy...) that will be on top of your docker registry (and not the UI!) to override OPTIONS requests.
If your docker registry does not need credentials, you will need to send this HEADER:
<pre><code class="lang-yml">http: headers: Access-Control-Allow-Origin: ['*'] Access-Control-Allow-Headers: ['Accept', 'Cache-Control'] Access-Control-Allow-Methods: ['HEAD', 'GET', 'OPTIONS'] # Optional</code></pre>
If your docker registry need credentials, you will need to send these HEADERS (you must add the protocol http/https and the port when not default 80/443):
<pre><code class="lang-yml">http: headers: Access-Control-Allow-Origin: ['http://registry-ui.example.com'] Access-Control-Allow-Credentials: [true] Access-Control-Allow-Headers: ['Authorization', 'Accept', 'Cache-Control'] Access-Control-Allow-Methods: ['HEAD', 'GET', 'OPTIONS'] # Optional</code></pre>
An alternative for CORS issues is a plugin on your browser, more info here (thank you xmontero).
Using delete
For deleting images, you need to activate the delete feature in the UI with DELETE_IMAGES=true` and in your registry:
storage:
delete:
enabled: true
And you need to add these HEADERS:
http:
headers:
Access-Control-Allow-Methods: ['HEAD', 'GET', 'OPTIONS', 'DELETE']
Access-Control-Allow-Headers: ['Authorization', 'Accept', 'Cache-Control']
Access-Control-Expose-Headers: ['Docker-Content-Digest']
Registry example
Example of docker registry configuration file:
version: 0.1
log:
fields:
service: registry
storage:
delete:
enabled: true
cache:
blobdescriptor: inmemory
filesystem:
rootdirectory: /var/lib/registry
http:
addr: :5000
headers:
X-Content-Type-Options: [nosniff]
Access-Control-Allow-Origin: ['http://127.0.0.1:8000']
Access-Control-Allow-Methods: ['HEAD', 'GET', 'OPTIONS', 'DELETE']
Access-Control-Allow-Headers: ['Authorization', 'Accept', 'Cache-Control']
Access-Control-Max-Age: [1728000]
Access-Control-Allow-Credentials: [true]
Access-Control-Expose-Headers: ['Docker-Content-Digest']
auth:
htpasswd:
realm: basic-realm
path: /etc/docker/registry/htpasswd
Standalone Application
If you do not want to install the docker-registry-ui on your server, you may check out the Electron standalone application (not updated).
All examples
- Use docker-registry-ui as a proxy (use REGISTRYURL)
- Use docker-registry-ui as standalone (use URL)
- Use docker-registry-ui with traefik
- Use docker-registry-ui with docker registry and Amazon s3 (#75)
- FIX revproxy to registry does not work when published under non-root url (#73)
- Use docker-registry-ui with HTTPS (#20)
- Unable to push image when docker-registry-ui is used as a proxy on non 80 port (#88)
- Add custom headers bases on environment variable and/or file when the ui is used as proxy (#89)
- UI showing same sha256 content digest for all tags + Delete is not working (#116)
- Electron-based Standalone Application (#129)
- Use docker-registry-ui as proxy with read-only right (#47)
- Use DEFAULTREGISTRIES and READONLYREGISTRIES (#219)