diff --git a/README.md b/README.md index 09c39af..1428944 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Docker Registry UI ## Overview + This project aims to provide a user interface for your private docker registry v2. There is no default registry on this UI, you should add your own with the UI. You can manage more than one registry server. @@ -12,13 +13,14 @@ This web user interface use [Riot](https://github.com/Riot/riot) the react-like ## Features - * List all your repositories/images. - * List all tags for a repository/image - * Sort the tag list - * One interface for many registry - * Use a secured docker registry +- List all your repositories/images. +- List all tags for a repository/image +- Sort the tag list +- One interface for many registry +- Use a secured docker registry ## Getting Started + ### Basic First you need node and npm in order to download dependencies. @@ -30,36 +32,59 @@ npm install ``` Now you can open index.html with your browser or use a http-server + ```sh npm install -g http-server http-server ``` + ### Docker + The docker contains the source code and a node webserver in order to serve the docker-registry-ui. #### Get the docker image + You can get the image in three ways From sources with this command : + ```sh git clone https://github.com/Joxit/docker-registry-ui.git docker build -t joxit/docker-registry-ui docker-registry-ui +docker build -t joxit/docker-registry-ui -f docker-registry-ui/Dockerfile.static docker-registry-ui ``` Or build with the url : - ```sh + +```sh docker build -t joxit/docker-registry-ui github.com/Joxit/docker-registry-ui +docker build -t joxit/docker-registry-ui -f Dockerfile.static github.com/Joxit/docker-registry-ui ``` Or pull the image from [docker hub](https://hub.docker.com/r/joxit/docker-registry-ui/) : + ```sh docker pull joxit/docker-registry-ui +docker pull joxit/docker-registry-ui:static ``` #### Run the docker -To run the docker and see the website on your 8080 port, try this : + +To run the docker and see the website on your 80 port, try this : + ```sh -docker run -d -p 8080:8080 joxit/docker-registry-ui +docker run -d -p 80:80 joxit/docker-registry-ui +``` + +#### Run the static docker + +Some env options are available for use this interface for only one server. + +- `URL`: set the static URL to use. (`Required`) +- `DELETE_IMAGES`: if this variable is empty or `false`, delete feature is desactivated. It is activated otherwise. + +```sh +docker run -d -p 80:80 -e URL=http://127.0.0.1:5000 -e DELETE_IMAGES=true joxit/docker-registry-ui:static ``` ## Using CORS @@ -67,13 +92,66 @@ docker run -d -p 8080:8080 joxit/docker-registry-ui 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: '*' -``` + + Access-Control-Allow-Origin: '*' If your docker registry need credentials, you will need to send these HEADERS : + +```yml +http: + headers: + Access-Control-Allow-Origin: '' + Access-Control-Allow-Credentials: true + Access-Control-Allow-Methods: ['HEAD', 'GET', 'OPTIONS'] # Optional ``` -Access-Control-Allow-Origin: '' -Access-Control-Allow-Credentials: true -Access-Control-Allow-Methods: ['HEAD', 'GET', 'OPTIONS'] # Optional + +## Using delete + +For deleting images, you need to activate the delete feature in your registry : + +```yml +storage: + delete: + enabled: true +``` + +And you need to add these HEADERS : + +```yml +http: + headers: + Access-Control-Allow-Methods: ['HEAD', 'GET', 'OPTIONS', 'DELETE'] + Access-Control-Expose-Headers: ['Docker-Content-Digest'] +``` + +## Registry example + +Example of docker registry configuration file: + +```yml +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:8001'] + Access-Control-Allow-Methods: ['HEAD', 'GET', 'OPTIONS', 'DELETE'] + Access-Control-Allow-Headers: ['Authorization'] + 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 ``` diff --git a/bin/entrypoint b/bin/entrypoint index 17f7fe6..27fc379 100755 --- a/bin/entrypoint +++ b/bin/entrypoint @@ -2,6 +2,10 @@ $@ sed -i "s,\${URL},${URL}," scripts/script.js +if [ -z "${DELETE_IMAGES}" ] || [ "${DELETE_IMAGES}" = false ] ; then + sed -i "s/registryUI.isImageRemoveActivated *= *[^,;]*/registryUI.isImageRemoveActivated=false/" scripts/script.js +fi + if [ -z "$@" ]; then nginx -g "daemon off;" else diff --git a/gulpfile.js b/gulpfile.js index f3b9ce1..35a579b 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -49,7 +49,7 @@ gulp.task('riot-tag', ['html'], function() { }); gulp.task('riot-static-tag', ['html'], function() { - return gulp.src(['src/tags/catalog.tag', 'src/tags/app.tag', 'src/tags/taglist.tag']) + return gulp.src(['src/tags/catalog.tag', 'src/tags/app.tag', 'src/tags/taglist.tag', 'src/tags/remove-image.tag']) .pipe(concat('tags-static.js')) .pipe(riot()) .pipe(minifier({}, uglify)) diff --git a/src/index.html b/src/index.html index 1d2d724..4c3808b 100644 --- a/src/index.html +++ b/src/index.html @@ -68,6 +68,7 @@ + diff --git a/src/scripts/http.js b/src/scripts/http.js index 0f485ac..3f0ecb1 100644 --- a/src/scripts/http.js +++ b/src/scripts/http.js @@ -17,6 +17,7 @@ function Http() { this.oReq = new XMLHttpRequest(); this._events = {}; + this._headers = {}; } Http.prototype.addEventListener = function(e, f) { @@ -31,6 +32,9 @@ Http.prototype.addEventListener = function(e, f) { for (key in this.http._events) { req.addEventListener(key, this.http._events[key]); } + for (key in this.http._headers) { + req.setRequestHeader(key, this.http._headers[key]); + } req.withCredentials = true; req.open(this.http._method, this.http._url); req.send(); @@ -50,6 +54,11 @@ Http.prototype.addEventListener = function(e, f) { } }; +Http.prototype.setRequestHeader = function(header, value) { + this.oReq.setRequestHeader(header, value); + this._headers[header] = value; +}; + Http.prototype.open = function(m, u) { this._method = m; this._url = u; diff --git a/src/scripts/script.js b/src/scripts/script.js index 2e6c873..7bef7a1 100644 --- a/src/scripts/script.js +++ b/src/scripts/script.js @@ -60,6 +60,7 @@ registryUI.removeServer = function(url) { registryServer.splice(index, 1); localStorage.setItem('registryServer', JSON.stringify(registryServer)); } +registryUI.isImageRemoveActivated = true; registryUI.catalog = {}; registryUI.taglist = {}; diff --git a/src/scripts/static.js b/src/scripts/static.js index cb9c0af..62ac604 100644 --- a/src/scripts/static.js +++ b/src/scripts/static.js @@ -17,7 +17,8 @@ var registryUI = {} registryUI.url = function() { return '${URL}'; -} +}; +registryUI.isImageRemoveActivated = true; registryUI.catalog = {}; registryUI.taglist = {}; diff --git a/src/tags/remove-image.tag b/src/tags/remove-image.tag new file mode 100644 index 0000000..c326277 --- /dev/null +++ b/src/tags/remove-image.tag @@ -0,0 +1,63 @@ + + + + delete + + + diff --git a/src/tags/taglist.tag b/src/tags/taglist.tag index 59801cb..0a3513a 100644 --- a/src/tags/taglist.tag +++ b/src/tags/taglist.tag @@ -30,12 +30,16 @@ Repository Tag + { registryUI.taglist.name } { item } + + + @@ -110,6 +114,9 @@ registryUI.taglist.back = function () { rg.router.go('home'); }; + registryUI.taglist.refresh = function () { + rg.router.go(rg.router.current.name, rg.router.current.params); + }; \ No newline at end of file