/docker-registry-ui

The simplest and most complete UI for your private registry

Primary LanguageRiotGNU Affero General Public License v3.0AGPL-3.0

title
Docker Registry User Interface

Docker Registry UI

Stars Pulls Sponsor Artifact Hub

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 registeries (same behavior as the old static tag).

You may need the migration guide from 1.x to 2.x or the 1.x readme

This web user interface uses Riot the react-like user interface micro-library and riot-mui components.

Project Page, Live Demo, Examples, Helm Chart

preview

If you like my work and want to support it, don't hesitate to sponsor me.

Features

  • List all your repositories/images.
  • List all tags for a image.
  • Sort the tag list with number compatibility (see #46).
  • Use a secured docker registry.
  • Display image size (see #30).
  • Multi arch supports, Alpine and Debian based images with supports for arm32v7 and arm64v8.
  • Copy docker pull command to clipboard (see #42).
  • Show sha256 for specific tag (hover image tag).
  • Display image creation date (see #49)
  • Display image history (see #58 & #61).
  • Image aggregation (see #56).
  • Display image/tag count (see #56 issue comment).
  • Select multiple tags to delete (see #29).
  • Select all tags with ALT + Click to delete (see #80).
  • One interface for many registries (when SINGLE_REGISTRY=false).
  • Share your docker registry with query parameter url (e.g. https://joxit.dev/docker-registry-ui/demo?url=https://registry.example.com) (when SINGLE_REGISTRY=false).
  • Use the UI as reverse proxy (with NGINX_PROXY_PASS_URL environment variable) to your docker registry (This will avoid CORS).
  • Add Title when using REGISTRY_TITLE (see #28).
  • Customise docker pull command on static registry UI (see #71).
  • Add custom header via environment variable and file via NGINX_PROXY_HEADER_* (see #89)
  • Show/Hide content digest in taglist via SHOW_CONTENT_DIGEST (values are: [true, false], default: false) (see #126).
  • Limit the number of elements in the image list via CATALOG_ELEMENTS_LIMIT (see #127).
  • Multi arch support in history page (see #130 and #134)
  • Set a list of default registries with DEFAULT_REGISTRIES (see #219).
  • Desactivate add and remove regisitries with READ_ONLY_REGISTRIES (see #219).
  • Filter images and tags with a search bar. You can select the search bar with the shortcut CRTL + F or F3. When the search bar is already focused, the shortcut will fallback to the default behavior (see #213).
  • Forward custom header to your backend registry via environment variable and file via NGINX_PROXY_PASS_HEADER_* (see #206).
  • Run the container with user nginx instead of root via --user nginx and listend on custom port via NGINX_LISTEN_PORT (see #224).
  • Show number of tags per images on catalog page. This will produce + nb images requests, not recommended on large registries via SHOW_CATALOG_NB_TAGS (default: false) (see #161 and #239).
  • Expose custom labels in history page, custom labels will be processed like maintainer label via HISTORY_CUSTOM_LABELS (see #160 and #240).
  • Access to the official Helm Chart: https://helm.joxit.dev/

FAQ

  • What is the difference between SINGLE_REGISTRY=false and SINGLE_REGISTRY=true options ?
    • When 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 ?
    • This is a limitation of docker registry, the garbage collector don't remove empty images. If you want to delete dangling images, you will need to delete the folder in your registry data. (see #77)
  • Why the image size in the UI is not the same as displayed during docker images ?
    • The UI displays the compressed size of the image and not the extracted size version.
  • Can I use HTTPS on the UI ?
    • Yes, put your favourite reverse proxy on the front of the UI. Your reverse proxy will take care of HTTPS connection.
  • Does the UI support authentication ?
    • Yes, but it supports only basic auth. It's a simple standalone frontend, it will use your browser window for authentication.
  • Can I use the UI and docker client with an insecure registry (registry url without https) ?
    • Yes you can, you must first configure your docker client. (see #76)
  • What does Mixed Content error mean ?
    • This means you are using a UI with HTTPS and your registry is using HTTP (unsecured). When you are on a HTTPS site, you can't get HTTP content. Upgrade you registry with a HTTPS connection.
  • Why the default nginx Host is set to $http_host ?
    • This fixes the issue #88. More about this in #113.
  • Why OPTIONS (aka preflight requests) and DELETE fails with 401 status code (using Basic Auth) ?
    • This is caused by a bug in docker registry, it returns 401 status requests on preflight requests, this breaks W3C preflight-request specification. I suggest to have your UI on the same domain than your registry e.g. registry.example.com/ui/ or use NGINX_PROXY_PASS_URL or configure a nginx/apache/haproxy in front of your registry that returns 200 on each OPTIONS requests. (see #104, #204, #207, #214, #266).
  • Can I use the docker registry ui as a standalone application (with Electron) ?
    • Yes, check out the example here. (see #129)
  • I deleted images through the UI, but they are still present on the server. How can I delete them?
    • When you delete an image with the UI, only the reference is deleted and not the content. To remove dangling images, you need to run the garbage collector of the registry with the command 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 ?
    • This a docker registry API limitation, there is only one way to delete images with tag, it's by its 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 ?
    • Yes you can run the container with the nginx user, (see #224).
  • Can I use the UI with a docker hub mirror and show library/* images ?
    • Yes but it is at your own risk using two regstry servers, check the comment #155.
  • How to fix CORS issue on s3 bucket ?
    • You should add a CORS Policy on your bucket, check the issue #193.

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.

  • 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.g http://registry.example.com). (default: derived from the hostname of your UI).
  • REGISTRY_TITLE: Set a custom title for your user interface. (default: value derived from REGISTRY_URL).
  • PULL_URL: Set a custom url when you copy the docker pull command. (default: value derived from REGISTRY_URL).
  • DELETE_IMAGES: Set if we can delete images from the UI. (default: false)
  • SHOW_CONTENT_DIGEST: Show content digest in docker tag list. (default: false)
  • CATALOG_ELEMENTS_LIMIT: Limit the number of elements in the catalog page. (default: 100000).
  • SINGLE_REGISTRY: Remove the menu that show the dialogs to add, remove and change the endpoint of your docker registry. (default: false).
  • NGINX_PROXY_PASS_URL: Update the default Nginx configuration and set the proxy_pass to your backend docker registry (this avoid CORS configuration). This is usually the name of your registry container in the form http://registry:5000.
  • NGINX_PROXY_HEADER_*: Update the default Nginx configuration and set custom headers for your backend docker registry. Only when NGINX_PROXY_PASS_URL is used.
  • NGINX_PROXY_PASS_HEADER_*: Update the default Nginx configuration and forward custom headers to your backend docker registry. Only when NGINX_PROXY_PASS_URL is used.
  • NGINX_LISTEN_PORT: Listen on a port other than 80. (default: 80 when the user is root, 8080 otherwise).
  • DEFAULT_REGISTRIES: List of comma separated registry URLs (e.g http://registry.example.com,http://registry:5000), available only when SINGLE_REGISTRY=false. (default: ).
  • READ_ONLY_REGISTRIES: Desactivate dialog for remove and add new registries, available only when SINGLE_REGISTRY=false. (default: false).
  • SHOW_CATALOG_NB_TAGS: Show number of tags per images on catalog page. This will produce + nb images requests, not recommended on large registries. (default: false).
  • HISTORY_CUSTOM_LABELS: Expose custom labels in history page, custom labels will be processed like maintainer label.
  • USE_CONTROL_CACHE_HEADER: Use Control-Cache header and set to no-store, no-cache. This will avoid some issues on multi-arch images (see #260). This option requires registry configuration: Access-Control-Allow-Headers with Cache-Control. (default: false).
  • THEME: Chose your default theme, could be dark, light or auto. (default: auto). Since 2.4.0
  • THEME_*: See table in Theme options section. Since 2.4.0

There are some examples with docker-compose and docker-registry-ui as proxy here or docker-registry-ui as standalone here.

Theme options

This featureswas added to version 2.4.0. See more about this in #283.

Environment variable light theme value dark theme value
THEME_PRIMARY_TEXT #25313b #8A9EBA
THEME_NEUTRAL_TEXT #777777 #36527A
THEME_BACKGROUND #ffffff #22272e
THEME_HOVER_BACKGROUND #eeeeee #30404D
THEME_ACCENT_TEXT #6680a1 #5684FF
THEME_HEADER_TEXT #ffffff #ffffff
THEME_HEADER_BACKGROUND #25313b #333A45
THEME_FOOTER_TEXT #ffffff #ffffff
THEME_FOOTER_NEUTRAL_TEXT #999999 #999999
THEME_FOOTER_BACKGROUND #555555 #555555

Using CORS

Your server should be configured to accept CORS.

If your docker registry does not need credentials, you will need to send this HEADER:

Access-Control-Allow-Origin: ['*']

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):

http:
  headers:
    Access-Control-Allow-Origin: ['http://registry.example.com']
    Access-Control-Allow-Credentials: [true]
    Access-Control-Allow-Headers: ['Authorization', 'Accept', 'Cache-Control']
    Access-Control-Allow-Methods: ['HEAD', 'GET', 'OPTIONS'] # Optional

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 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']

If you are running the static interface don't forget the environment variable DELETE_IMAGES.

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.

All examples