Compare commits

..

13 Commits
1.4.0 ... 1.4.7

Author SHA1 Message Date
Joxit
01d8bcfccd feat(footer): reduce footer size 2020-02-02 15:16:47 +01:00
Joxit
c60c2f3e95 feat(catalog): indent aggregated entries differently
resolves #121
2020-02-01 23:45:16 +01:00
Joxit
241ee0fd13 fix(delete): alt+click every time with better messages when no digest
fixes #120
2020-01-28 23:03:08 +01:00
Joxit
2e915a82b1 fix(delete): fix bug introduced in 1.4.3
resolves #119
2020-01-27 00:17:36 +01:00
Joxit
e3d592ac65 fix: UI showing same sha256 content digest for all tags when using credentials
resolves #116
2020-01-26 12:25:56 +01:00
Joxit
531f9400a0 chore: add example for #116 2020-01-26 12:00:22 +01:00
Joxit
d7f6cd7e1a chore: update readme for delete issue from #104 2020-01-25 00:37:00 +01:00
Joxit
8524c0d18b fix(delete): update the message and wrap the delete function for onclick 2020-01-20 00:11:45 +01:00
Joxit
8b7bd6cfb8 fix: Default value for NGINX_PROXY_HEADER_Host is $http_host
Remove the Proxy header from default.conf

fixes #113
2020-01-19 08:49:58 +01:00
Joxit
f56cd055a2 chore: add @pidario as contributor 🎉 2020-01-10 21:45:32 +04:00
Joxit
79203787bd fix: add supports to oci images (containers/buildah)
Fixes #114
2020-01-10 21:38:43 +04:00
Jones Magloire
32d895a09d Merge pull request #112 from das7pad/misc-fix-typo
[misc] fix a typo in CONTRIBUTORS
2019-11-14 14:38:04 +01:00
Jakob Ackermann
bc26eca908 [misc] fix a typo in a section title of the CONTRIBUTORS file
Signed-off-by: Jakob Ackermann <das7pad@outlook.com>
2019-11-13 15:51:59 +01:00
23 changed files with 137 additions and 44 deletions

View File

@@ -27,7 +27,7 @@ My docker-compose file
```
My private docker registry configuration
My private docker registry configuration
```yml
```
@@ -41,18 +41,18 @@ A clear and concise description of what you expected to happen.
If applicable, add screenshots to help explain your problem.
## System information
- OS: [e.g. Debian 10, Windows, Android 9...]
<!-- Browser is only for UI bugs -->
- Browser:
- Name: [e.g. Chrome, Firefox...]
- Version: [e.g. 22]
- Docker registry UI:
- Version: [e.g. 1.3.0]
- Interface variant: [standard or static]
- Version: [e.g. 1.4.0]
- Server: [docker or dist]
<!-- Only for Docker and for where the UI is hosted -->
- Docker version: [e.g. 19.03]
- Docker registry ui tag: [latest, static, master, 1.4-static...]
- OS/Arch: [e.g. linux/amd64]
- Tools: [e.g. docker-compose, kubernets..]

View File

@@ -12,7 +12,7 @@
- Vladimir Kozyrev [@fieryvova](https://github.com/fieryvova)
- Haibo Jia [@bluethon](https://github.com/bluethon)
## Beceause committers are not the only contributors
## Because committers are not the only contributors
- Ewout Prangsma [@ewoutp](https://github.com/ewoutp)
- [@soosap](https://github.com/soosap)
@@ -24,3 +24,6 @@
- [@wuyue92tree](https://github.com/wuyue92tree)
- Giovanni Toraldo [@gionn](https://github.com/gionn)
- [@marcusblake](https://github.com/marcusblake)
- Dario [@pidario](https://github.com/pidario)
- Jernej K. [@Cvetk0](https://github.com/Cvetk0)
- Cristian Posoiu [@cr1st1p](https://github.com/cr1st1p)

View File

@@ -20,7 +20,7 @@ In the **static interface**, it will connect to a single registry and will not c
This web user interface uses [Riot](https://github.com/Riot/riot) the react-like user interface micro-library and [riot-mui](https://github.com/kysonic/riot-mui) components.
## [Project Page](https://joxit.dev/docker-registry-ui), [Live Demo](https://joxit.dev/docker-registry-ui/demo/) [Examples](https://github.com/Joxit/docker-registry-ui/tree/master/examples)
## [Project Page](https://joxit.dev/docker-registry-ui), [Live Demo](https://joxit.dev/docker-registry-ui/demo/), [Examples](https://github.com/Joxit/docker-registry-ui/tree/master/examples)
![preview](https://raw.github.com/Joxit/docker-registry-ui/master/docker-registry-ui.gif "Preview of Docker Registry UI")
@@ -61,6 +61,10 @@ This web user interface uses [Riot](https://github.com/Riot/riot) the react-like
- Yes you can, you must first configure your docker client. (see [#76](https://github.com/Joxit/docker-registry-ui/issues/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](https://github.com/Joxit/docker-registry-ui/issues/88). More about this in [#113](https://github.com/Joxit/docker-registry-ui/issues/113).
- Why DELETE fails with 401 status code (using Basic Auth) ?
- This is caused by a bug in docker registry, I suggest to have your UI on the same domain than your registry e.g. registry.example.com/ui/. (see [#104](https://github.com/Joxit/docker-registry-ui/issues/104)).
Need more informations ? Try my [examples](https://github.com/Joxit/docker-registry-ui/tree/master/examples) or open an issue.
@@ -236,8 +240,9 @@ auth:
- [Use docker-registry-ui as a proxy (use REGISTRY_URL)](https://github.com/Joxit/docker-registry-ui/tree/master/examples/ui-as-proxy)
- [Use docker-registry-ui as standalone (use URL)](https://github.com/Joxit/docker-registry-ui/tree/master/examples/ui-as-standalone)
- [Use docker-registry-ui with traefik](https://github.com/Joxit/docker-registry-ui/tree/master/examples/traefik)
- [Use docker-registry-ui with docker registry and Amazon s3](https://github.com/Joxit/docker-registry-ui/tree/master/examples/issue-75) ([#75](https://github.com/Joxit/docker-registry-ui/issues/88))
- [Use docker-registry-ui with docker registry and Amazon s3](https://github.com/Joxit/docker-registry-ui/tree/master/examples/issue-75) ([#75](https://github.com/Joxit/docker-registry-ui/issues/75))
- [FIX revproxy to registry does not work when published under non-root url](https://github.com/Joxit/docker-registry-ui/tree/master/examples/issue-73) ([#73](https://github.com/Joxit/docker-registry-ui/issues/73))
- [Use docker-registry-ui with HTTPS](https://github.com/Joxit/docker-registry-ui/tree/master/examples/issue-20) ([#20](https://github.com/Joxit/docker-registry-ui/issues/20))
- [Unable to push image when docker-registry-ui is used as a proxy on non 80 port](https://github.com/Joxit/docker-registry-ui/tree/master/examples/issue-88) ([#88](https://github.com/Joxit/docker-registry-ui/issues/88))
- [Add custom headers bases on environment variable and/or file when the ui is used as proxy](https://github.com/Joxit/docker-registry-ui/tree/master/examples/proxy-headers) ([#89](https://github.com/Joxit/docker-registry-ui/pull/89))
- [UI showing same sha256 content digest for all tags + Delete is not working](https://github.com/Joxit/docker-registry-ui/tree/master/examples/issue-116) ([#116](https://github.com/Joxit/docker-registry-ui/issues/116))

View File

@@ -18,6 +18,8 @@ LABEL maintainer="Jones MAGLOIRE @Joxit"
WORKDIR /usr/share/nginx/html/
ENV NGINX_PROXY_HEADER_Host '$http_host'
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
COPY dist/ /usr/share/nginx/html/
COPY dist/scripts/docker-registry-ui-static.js /usr/share/nginx/html/scripts/docker-registry-ui.js

View File

@@ -18,6 +18,8 @@ LABEL maintainer="Jones MAGLOIRE @Joxit"
WORKDIR /usr/share/nginx/html/
ENV NGINX_PROXY_HEADER_Host '$http_host'
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
COPY dist/ /usr/share/nginx/html/
COPY dist/scripts/docker-registry-ui-static.js /usr/share/nginx/html/scripts/docker-registry-ui.js

View File

@@ -18,6 +18,8 @@ LABEL maintainer="Jones MAGLOIRE @Joxit"
WORKDIR /usr/share/nginx/html/
ENV NGINX_PROXY_HEADER_Host '$http_host'
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
COPY dist/ /usr/share/nginx/html/
COPY dist/scripts/docker-registry-ui-static.js /usr/share/nginx/html/scripts/docker-registry-ui.js

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/style.css vendored

File diff suppressed because one or more lines are too long

View File

@@ -3,8 +3,9 @@
- [Use docker-registry-ui as a proxy (use REGISTRY_URL)](https://github.com/Joxit/docker-registry-ui/tree/master/examples/ui-as-proxy)
- [Use docker-registry-ui as standalone (use URL)](https://github.com/Joxit/docker-registry-ui/tree/master/examples/ui-as-standalone)
- [Use docker-registry-ui with traefik](https://github.com/Joxit/docker-registry-ui/tree/master/examples/traefik)
- [Use docker-registry-ui with docker registry and Amazon s3](https://github.com/Joxit/docker-registry-ui/tree/master/examples/issue-75) ([#75](https://github.com/Joxit/docker-registry-ui/issues/88))
- [Use docker-registry-ui with docker registry and Amazon s3](https://github.com/Joxit/docker-registry-ui/tree/master/examples/issue-75) ([#75](https://github.com/Joxit/docker-registry-ui/issues/75))
- [FIX revproxy to registry does not work when published under non-root url](https://github.com/Joxit/docker-registry-ui/tree/master/examples/issue-73) ([#73](https://github.com/Joxit/docker-registry-ui/issues/73))
- [Use docker-registry-ui with HTTPS](https://github.com/Joxit/docker-registry-ui/tree/master/examples/issue-20) ([#20](https://github.com/Joxit/docker-registry-ui/issues/20))
- [Unable to push image when docker-registry-ui is used as a proxy on non 80 port](https://github.com/Joxit/docker-registry-ui/tree/master/examples/issue-88) ([#88](https://github.com/Joxit/docker-registry-ui/issues/88))
- [Add custom headers bases on environment variable and/or file when the ui is used as proxy](https://github.com/Joxit/docker-registry-ui/tree/master/examples/proxy-headers) ([#89](https://github.com/Joxit/docker-registry-ui/pull/89))
- [Add custom headers bases on environment variable and/or file when the ui is used as proxy](https://github.com/Joxit/docker-registry-ui/tree/master/examples/proxy-headers) ([#89](https://github.com/Joxit/docker-registry-ui/pull/89))
- [UI showing same sha256 content digest for all tags + Delete is not working](https://github.com/Joxit/docker-registry-ui/tree/master/examples/issue-116) ([#116](https://github.com/Joxit/docker-registry-ui/issues/116))

View File

@@ -0,0 +1,42 @@
version: '2'
services:
registry-srv:
image: registry:2.7.1
restart: always
volumes:
- storage:/var/lib/registry
- ./htpasswd:/etc/docker/registry/htpasswd
ports:
- 5000:5000
environment:
- REGISTRY_HTTP_HEADERS_X-Content-Type-Options=[nosniff]
- REGISTRY_HTTP_HEADERS_Access-Control-Allow-Origin=['http://localhost']
- REGISTRY_HTTP_HEADERS_Access-Control-Allow-Methods=['HEAD', 'GET', 'OPTIONS', 'DELETE']
- REGISTRY_HTTP_HEADERS_Access-Control-Allow-Headers=['Authorization']
- REGISTRY_HTTP_HEADERS_Access-Control-Expose-Headers=['Docker-Content-Digest']
- REGISTRY_HTTP_HEADERS_Access-Control-Allow-Credentials=['true']
- REGISTRY_AUTH_HTPASSWD_REALM=basic-realm
- REGISTRY_AUTH_HTPASSWD_PATH=/etc/docker/registry/htpasswd
- REGISTRY_STORAGE_DELETE_ENABLED=true
networks:
- registry-ui-net
container_name: registry-srv
registry-ui:
image: joxit/docker-registry-ui:static
restart: always
ports:
- 80:80
environment:
- REGISTRY_TITLE=Private Docker Registry
- URL=http://localhost:5000
- DELETE_IMAGES=true
container_name: registry-ui
networks:
registry-ui-net:
volumes:
storage:
driver: local

View File

@@ -0,0 +1,3 @@
# login: registry
# password: ui
registry:$2y$11$1bmuJLK8HrQl5ACS/WeqRuJLUArUZfUcP2R23asmozEpfN76.pCHy

View File

@@ -20,8 +20,6 @@ services:
- REGISTRY_TITLE=Private Docker Registry
- REGISTRY_URL=http://registry-srv:5000
- DELETE_IMAGES=true
depends_on:
- debugproxy
networks:
- registry-ui-net
container_name: registry-ui

9
examples/populate-registry Executable file
View File

@@ -0,0 +1,9 @@
#!/bin/sh
REGISTRY="${1:-localhost:5000}"
for image in alpine:latest alpine:edge alpine:3.11 alpine:3.10 alpine:3.9; do
docker pull $image
docker tag $image $REGISTRY/$image
docker push $REGISTRY/$image
done

View File

@@ -24,7 +24,6 @@ server {
#! if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
#! return 404;
#! }
#! proxy_set_header Host $http_host;
#! ${NGINX_PROXY_HEADERS}
#! proxy_pass ${REGISTRY_URL};
#! }

View File

@@ -1,6 +1,6 @@
{
"name": "docker-registry-ui",
"version": "1.4.0",
"version": "1.4.7",
"scripts": {
"build": "./node_modules/gulp/bin/gulp.js build"
},

View File

@@ -65,6 +65,7 @@ Http.prototype.addEventListener = function(e, f) {
req.withCredentials = true;
req.hasHeader = Http.hasHeader;
req.getErrorMessage = Http.getErrorMessage;
self.oReq = req;
req.send();
} else {
f.bind(this)();

View File

@@ -282,6 +282,11 @@ material-button .content i.material-icons,
color: #777;
}
material-button[disabled] .content i.material-icons,
material-checkbox[disabled] .content i.material-icons {
color: #bbb;
}
material-snackbar .toast {
height: auto;
}
@@ -371,6 +376,10 @@ footer {
}
}
material-footer {
padding: 0.5em 1em;
}
@media screen and (min-width: 760px) and (max-height: 750px) {
main {
min-height: calc(100% - 144px - 2.5em);
@@ -511,8 +520,8 @@ catalog-element catalog-element.hide material-card {
opacity: 0;
}
catalog-element catalog-element .list > span i.material-icons {
margin-right: 48px;
catalog-element catalog-element > .content {
margin-left: 3em;
}
remove-image {

View File

@@ -202,6 +202,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
oReq.getContentDigest(function (digest) {
self.digest = digest;
self.trigger('content-digest', digest);
if (!digest) {
registryUI.showErrorCanNotReadContentDigest();
}
});
self.getBlobs(response.config.digest)
} else if (this.status == 404) {
@@ -211,7 +214,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
}
});
oReq.open('GET', registryUI.url() + '/v2/' + self.name + '/manifests/' + self.tag);
oReq.setRequestHeader('Accept', 'application/vnd.docker.distribution.manifest.v2+json');
oReq.setRequestHeader('Accept', 'application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.manifest.v1+json');
oReq.send();
};
@@ -239,7 +242,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
}
});
oReq.open('GET', registryUI.url() + '/v2/' + self.name + '/blobs/' + blob);
oReq.setRequestHeader('Accept', 'application/vnd.docker.distribution.manifest.v2+json');
oReq.setRequestHeader('Accept', 'application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.manifest.v1+json');
oReq.send();
};

View File

@@ -16,18 +16,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<catalog-element>
<!-- Begin of tag -->
<material-card class="list highlight" item="{item}" expanded="{expanded}">
<material-waves onmousedown="{launch}" center="true" color="#ddd" />
<span>
<i class="material-icons">send</i>
{ typeof opts.item === "string" ? opts.item : opts.item.repo }
<div if="{typeof opts.item !== "string"}" class="item-count right">
{ opts.item.images && opts.item.images.length } images
<i class="material-icons animated {expanded: opts.expanded}">expand_more</i>
</div>
</span>
</material-card>
<catalog-element if="{typeof opts.item !== "string"}" class="animated {hide: !expanded, expanding: expanding}" each="{item in item.images}" />
<div class="content">
<material-card class="list highlight" item="{item}" expanded="{expanded}">
<material-waves onmousedown="{launch}" center="true" color="#ddd" />
<span>
<i class="material-icons">send</i>
{ typeof opts.item === "string" ? opts.item : opts.item.repo }
<div if="{typeof opts.item !== "string"}" class="item-count right">
{ opts.item.images && opts.item.images.length } images
<i class="material-icons animated {expanded: opts.expanded}">expand_more</i>
</div>
</span>
</material-card>
<catalog-element if="{typeof opts.item !== "string"}" class="animated {hide: !expanded, expanding: expanding}" each="{item in item.images}" />
</div>
<script>
this.on('mount', function() {
const self = this;

View File

@@ -15,10 +15,10 @@ You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<remove-image>
<material-button waves-center="true" rounded="true" waves-color="#ddd" title="This will delete the image." if="{ !opts.multiDelete }">
<material-button waves-center="true" rounded="true" waves-color="#ddd" title="This will delete the image." if="{ !opts.multiDelete }" disabled="{ !this.digest }">
<i class="material-icons">delete</i>
</material-button>
<material-checkbox if="{ opts.multiDelete }" title="Select this tag to delete it."></material-checkbox>
<material-checkbox if="{ opts.multiDelete }" title="Select this tag to delete it." disabled="{ !this.digest }"></material-checkbox>
<script type="text/javascript">
const self = this;
@@ -29,13 +29,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
if (self.multiDelete == self.opts.multiDelete) {
return;
}
if (this.tags['material-button']) {
this.delete = this.tags['material-button'].root.onclick = function(ignoreError) {
if (self.tags['material-button']) {
self.delete = function(ignoreError) {
const name = self.opts.image.name;
const tag = self.opts.image.tag;
registryUI.taglist.go(name);
if (!self.digest) {
registryUI.showErrorCanNotReadContentDigest();
registryUI.snackbar('Information for ' + name + ':' + tag + ' are not yet loaded.');
return;
}
const oReq = new Http();
@@ -44,25 +44,28 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
registryUI.taglist.display()
registryUI.snackbar('Deleting ' + name + ':' + tag + ' image. Run `registry garbage-collect config.yml` on your registry');
} else if (this.status == 404) {
ignoreError || registryUI.errorSnackbar('Digest not found');
ignoreError || registryUI.errorSnackbar('Digest not found for this image in your registry.');
} else {
registryUI.snackbar(this.responseText);
}
});
oReq.open('DELETE', registryUI.url() + '/v2/' + name + '/manifests/' + self.digest);
oReq.setRequestHeader('Accept', 'application/vnd.docker.distribution.manifest.v2+json');
oReq.setRequestHeader('Accept', 'application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.manifest.v1+json');
oReq.addEventListener('error', function() {
registryUI.errorSnackbar('An error occurred when deleting image. Check if your server accept DELETE methods Access-Control-Allow-Methods: [\'DELETE\'].');
});
oReq.send();
};
self.tags['material-button'].root.onclick = function() {
self.delete();
}
}
if (this.tags['material-checkbox']) {
if (!this.opts.multiDelete && this.tags['material-checkbox'].checked) {
this.tags['material-checkbox'].toggle();
if (self.tags['material-checkbox']) {
if (!self.opts.multiDelete && self.tags['material-checkbox'].checked) {
self.tags['material-checkbox'].toggle();
}
this.tags['material-checkbox'].on('toggle', function() {
self.tags['material-checkbox'].on('toggle', function() {
registryUI.taglist.instance.trigger('toggle-remove-image', this.checked);
});
}
@@ -71,6 +74,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
opts.image.one('content-digest', function(digest) {
self.digest = digest;
self.update();
});
opts.image.trigger('get-content-digest');
</script>

View File

@@ -153,8 +153,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
return images;
};
registryUI.taglist.bulkDelete = function() {
registryUI.taglist.bulkDelete = function(e) {
if (self.multiDelete && self.toDelete > 0) {
if (e.altKey) {
self._getRemoveImageTags()
.filter(function(img) { return img.tags['material-checkbox'].checked; })
.forEach(function(img) { img.tags['material-checkbox'].toggle() });
}
self._getRemoveImageTags().filter(function(img) {
return img.tags['material-checkbox'].checked;
}).forEach(function(img) {
@@ -170,6 +175,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
checkbox._toggle = checkbox.toggle;
checkbox.toggle = function(e) {
if (e.altKey) {
if (!this.checked) { this._toggle(); }
self._getRemoveImageTags()
.filter(function(img) { return !img.tags['material-checkbox'].checked; })
.forEach(function(img) { img.tags['material-checkbox'].toggle() });

View File

@@ -30,6 +30,8 @@ LABEL maintainer="Jones MAGLOIRE @Joxit"
WORKDIR /usr/share/nginx/html/
ENV NGINX_PROXY_HEADER_Host '$http_host'
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /usr/app/dist/ /usr/share/nginx/html/
COPY --from=builder /usr/app/dist/scripts/docker-registry-ui-static.js /usr/share/nginx/html/scripts/docker-registry-ui.js