My name is Max and I'm a freelance DevOps and cloud engineer from Germany.
I gain, apply and pass on knowledge about how to setup modern infrastructure on a daily basis.
Web-based front end for multiple v1/v2 Docker registries
License: MIT License
My name is Max and I'm a freelance DevOps and cloud engineer from Germany.
I gain, apply and pass on knowledge about how to setup modern infrastructure on a daily basis.
Hi, very useful tool! I was just wondering if it is possible to restrict access to the frontend itself, with basic or something else?
Best Thomas
Hi,
Sometimes when I try to get the list of images(tags) from the big repo(more then 5 tags) I get an "Internal Server Error". It occurs only with tags which is built on the "windowsservercore" image. I have two registries - one of them is running on the Windows, second - on Linux. But the error occurs at requests to both registries.
Docker Version: 18.03.1-ce
Version of Registries: v2.6.2
192.168.36.195 - - [08/Jun/2018 08:04:54] "GET /registry/docker-proxy-ua HTTP/1.1" 200 -
[2018-06-08 08:05:06,332] ERROR in app: Exception on /registry/docker-proxy-ua/repo/mssql2017/ [GET]
Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "frontend.py", line 137, in tag_overview
repo=urldecode_filter(repo))
File "/usr/local/lib/python3.6/site-packages/flask/templating.py", line 135, in render_template
context, ctx.app)
File "/usr/local/lib/python3.6/site-packages/flask/templating.py", line 117, in _render
rv = template.render(context)
File "/usr/local/lib/python3.6/site-packages/jinja2/asyncsupport.py", line 76, in render
return original_render(self, *args, **kwargs)
File "/usr/local/lib/python3.6/site-packages/jinja2/environment.py", line 1008, in render
return self.environment.handle_exception(exc_info, True)
File "/usr/local/lib/python3.6/site-packages/jinja2/environment.py", line 780, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.6/site-packages/jinja2/_compat.py", line 37, in reraise
raise value.with_traceback(tb)
File "/root/templates/tag_overview.html", line 1, in top-level template code
{% extends "layout.html" %}
File "/root/templates/layout.html", line 21, in top-level template code
<div id="content" class="container-fluid">{% block content %}{% endblock %}</div>
File "/root/templates/tag_overview.html", line 21, in block "content"
<td>{{ registry.get_size_of_layers(repo, tag) | to_mb }} MB</td>
File "/root/docker_registry_frontend/registry.py", line 97, in get_size_of_layers
result += self.get_size_of_layer(repo, image_id)
File "/root/docker_registry_frontend/cache.py", line 21, in decorator
result = f(*args, **kwargs)
File "/root/docker_registry_frontend/registry.py", line 338, in get_size_of_layer
method='HEAD'
File "/root/docker_registry_frontend/registry.py", line 64, in request
return urllib.request.urlopen(request, timeout=3)
File "/usr/local/lib/python3.6/urllib/request.py", line 223, in urlopen
return opener.open(url, data, timeout)
File "/usr/local/lib/python3.6/urllib/request.py", line 526, in open
response = self._open(req, data)
File "/usr/local/lib/python3.6/urllib/request.py", line 544, in _open
'_open', req)
File "/usr/local/lib/python3.6/urllib/request.py", line 504, in _call_chain
result = func(*args)
File "/usr/local/lib/python3.6/urllib/request.py", line 1346, in http_open
return self.do_open(http.client.HTTPConnection, req)
File "/usr/local/lib/python3.6/urllib/request.py", line 1321, in do_open
r = h.getresponse()
File "/usr/local/lib/python3.6/http/client.py", line 1331, in getresponse
response.begin()
File "/usr/local/lib/python3.6/http/client.py", line 297, in begin
version, status, reason = self._read_status()
File "/usr/local/lib/python3.6/http/client.py", line 258, in _read_status
line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
File "/usr/local/lib/python3.6/socket.py", line 586, in readinto
return self._sock.recv_into(b)
socket.timeout: timed out
192.168.36.195 - - [08/Jun/2018 08:05:06] "GET /registry/docker-proxy-ua/repo/mssql2017/ HTTP/1.1" 500 -
Hi,
Can I set somehow how many elements are list on the gui? Default is 10 i can see, but I would like to increase it.
Thanks,
Mihaly
@brennerm I tried running the image from docker hub, and it fails to start:
[root~]# docker run -p 127.0.0.1:80:80 brennerm/docker-registry-frontend
* Starting nginx nginx
...done.
Fatal Python error: getrandom() failed
Aborted (core dumped)
Kernel: 3.10.0-229.el7.x86_64
Using the docker image after configuring registry url I got the following exception:
[2017-07-06 12:24:00,923] ERROR in app: Exception on / [GET]
Traceback (most recent call last):
File "/usr/local/lib/python3.5/dist-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python3.5/dist-packages/flask/app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python3.5/dist-packages/flask/app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.5/dist-packages/flask/_compat.py", line 33, in reraise
raise value
File "/usr/local/lib/python3.5/dist-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python3.5/dist-packages/flask/app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "main.py", line 54, in registry_overview
registries=registry_web.registries)
File "/usr/local/lib/python3.5/dist-packages/flask/templating.py", line 134, in render_template
context, ctx.app)
File "/usr/local/lib/python3.5/dist-packages/flask/templating.py", line 116, in _render
rv = template.render(context)
File "/usr/local/lib/python3.5/dist-packages/jinja2/environment.py", line 1008, in render
return self.environment.handle_exception(exc_info, True)
File "/usr/local/lib/python3.5/dist-packages/jinja2/environment.py", line 780, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.5/dist-packages/jinja2/_compat.py", line 37, in reraise
raise value.with_traceback(tb)
File "/root/templates/registry_overview.html", line 1, in top-level template code
{% extends "layout.html" %}
File "/root/templates/layout.html", line 21, in top-level template code
<div id="content" class="container-fluid">{% block content %}{% endblock %}</div>
File "/root/templates/registry_overview.html", line 29, in block "content"
<td>{{ registry.get_number_of_repos() }}</td>
File "/root/docker_registry_frontend/registry.py", line 79, in get_number_of_repos
return len(self.get_repos())
File "/root/docker_registry_frontend/registry.py", line 315, in get_repos
url=self._url)
File "/root/docker_registry_frontend/registry.py", line 53, in json_request
DockerRegistry.string_request(*args, **kwargs)
File "/root/docker_registry_frontend/cache.py", line 21, in decorator
result = f(*args, **kwargs)
File "/root/docker_registry_frontend/registry.py", line 59, in string_request
return DockerRegistry.request(*args, **kwargs).read().decode()
File "/root/docker_registry_frontend/registry.py", line 64, in request
return urllib.request.urlopen(request, timeout=3)
File "/usr/lib/python3.5/urllib/request.py", line 163, in urlopen
return opener.open(url, data, timeout)
File "/usr/lib/python3.5/urllib/request.py", line 472, in open
response = meth(req, response)
File "/usr/lib/python3.5/urllib/request.py", line 582, in http_response
'http', request, response, code, msg, hdrs)
File "/usr/lib/python3.5/urllib/request.py", line 510, in error
return self._call_chain(*args)
File "/usr/lib/python3.5/urllib/request.py", line 444, in _call_chain
result = func(*args)
File "/usr/lib/python3.5/urllib/request.py", line 590, in http_error_default
raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 401: Unauthorized
127.0.0.1 - - [06/Jul/2017 12:24:00] "GET / HTTP/1.0" 500
When deleting a tag from docker-registry-frontend, I get a generic Internal Server Error.
Looking into the logs of the container, it seems that the registry itself reponds with a 301 Moved Permanently.
[2018-06-07 08:19:07,589] ERROR in app: Exception on /delete_tag [POST]
Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "frontend.py", line 112, in delete_tag
registry.delete_tag(repo, tag)
File "/root/docker_registry_frontend/registry.py", line 290, in delete_tag
method='DELETE'
File "/root/docker_registry_frontend/registry.py", line 64, in request
return urllib.request.urlopen(request, timeout=3)
File "/usr/local/lib/python3.6/urllib/request.py", line 223, in urlopen
return opener.open(url, data, timeout)
File "/usr/local/lib/python3.6/urllib/request.py", line 532, in open
response = meth(req, response)
File "/usr/local/lib/python3.6/urllib/request.py", line 642, in http_response
'http', request, response, code, msg, hdrs)
File "/usr/local/lib/python3.6/urllib/request.py", line 564, in error
result = self._call_chain(*args)
File "/usr/local/lib/python3.6/urllib/request.py", line 504, in _call_chain
result = func(*args)
File "/usr/local/lib/python3.6/urllib/request.py", line 735, in http_error_302
new = self.redirect_request(req, fp, code, msg, headers, newurl)
File "/usr/local/lib/python3.6/urllib/request.py", line 673, in redirect_request
raise HTTPError(req.full_url, code, msg, headers, fp)
urllib.error.HTTPError: HTTP Error 301: Moved Permanently
127.0.0.1 - - [07/Jun/2018 08:19:07] "POST /delete_tag?registry_name=registryname&repo=reponame&tag=tag-PR-39 HTTP/1.0" 500 -
Compose setup:
version: "3"
services:
registry:
image: registry:2
ports:
- 127.0.0.1:5000:5000
environment:
- REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/data
- REGISTRY_STORAGE_DELETE_ENABLED=true
volumes:
- ./data:/data
networks:
- reg
registry2-frontend:
image: brennerm/docker-registry-frontend
ports:
- "5002:80"
networks:
- reg
networks:
reg:
And the registry has been added with the following URL:
http://registry:5000/
Note that registry:2
points to the latest 2.6.2 image from Docker Hub.
Tried using via Portainer, and then just locally.
Can Get the initial splash screen, but as soon as I add my reg, I get a "Failed to load resource: the server responded with a status of 500 (INTERNAL SERVER ERROR)" message and can't do anything from that point forward.
Here is the error log:
2017-06-29T19:27:21.847857904Z [2017-06-29 19:27:21,843] ERROR in app: Exception on / [GET] 2017-06-29T19:27:21.847913460Z Traceback (most recent call last): 2017-06-29T19:27:21.847934667Z File "/usr/local/lib/python3.5/dist-packages/flask/app.py", line 1982, in wsgi_app 2017-06-29T19:27:21.847954915Z response = self.full_dispatch_request() 2017-06-29T19:27:21.847979054Z File "/usr/local/lib/python3.5/dist-packages/flask/app.py", line 1614, in full_dispatch_request 2017-06-29T19:27:21.847999283Z rv = self.handle_user_exception(e) 2017-06-29T19:27:21.848018452Z File "/usr/local/lib/python3.5/dist-packages/flask/app.py", line 1517, in handle_user_exception 2017-06-29T19:27:21.848038365Z reraise(exc_type, exc_value, tb) 2017-06-29T19:27:21.848057320Z File "/usr/local/lib/python3.5/dist-packages/flask/_compat.py", line 33, in reraise 2017-06-29T19:27:21.848077192Z raise value 2017-06-29T19:27:21.848096120Z File "/usr/local/lib/python3.5/dist-packages/flask/app.py", line 1612, in full_dispatch_request 2017-06-29T19:27:21.848116102Z rv = self.dispatch_request() 2017-06-29T19:27:21.848135113Z File "/usr/local/lib/python3.5/dist-packages/flask/app.py", line 1598, in dispatch_request 2017-06-29T19:27:21.848154925Z return self.view_functions[rule.endpoint](**req.view_args) 2017-06-29T19:27:21.848174199Z File "main.py", line 54, in registry_overview 2017-06-29T19:27:21.848193518Z registries=registry_web.registries) 2017-06-29T19:27:21.848212526Z File "/usr/local/lib/python3.5/dist-packages/flask/templating.py", line 134, in render_template 2017-06-29T19:27:21.848232315Z context, ctx.app) 2017-06-29T19:27:21.848284506Z File "/usr/local/lib/python3.5/dist-packages/flask/templating.py", line 116, in _render 2017-06-29T19:27:21.848305480Z rv = template.render(context) 2017-06-29T19:27:21.848324837Z File "/usr/local/lib/python3.5/dist-packages/jinja2/environment.py", line 1008, in render 2017-06-29T19:27:21.848344702Z return self.environment.handle_exception(exc_info, True) 2017-06-29T19:27:21.848363998Z File "/usr/local/lib/python3.5/dist-packages/jinja2/environment.py", line 780, in handle_exception 2017-06-29T19:27:21.848383949Z reraise(exc_type, exc_value, tb) 2017-06-29T19:27:21.848403058Z File "/usr/local/lib/python3.5/dist-packages/jinja2/_compat.py", line 37, in reraise 2017-06-29T19:27:21.848422814Z raise value.with_traceback(tb) 2017-06-29T19:27:21.848441844Z File "/root/templates/registry_overview.html", line 1, in top-level template code 2017-06-29T19:27:21.848461667Z {% extends "layout.html" %} 2017-06-29T19:27:21.848480983Z File "/root/templates/layout.html", line 21, in top-level template code 2017-06-29T19:27:21.848500622Z <div id="content" class="container-fluid">{% block content %}{% endblock %}</div> 2017-06-29T19:27:21.848521832Z File "/root/templates/registry_overview.html", line 29, in block "content" 2017-06-29T19:27:21.848541828Z <td>{{ registry.get_number_of_repos() }}</td> 2017-06-29T19:27:21.848565595Z File "/root/docker_registry_frontend/registry.py", line 79, in get_number_of_repos 2017-06-29T19:27:21.848585734Z return len(self.get_repos()) 2017-06-29T19:27:21.848604971Z File "/root/docker_registry_frontend/registry.py", line 315, in get_repos 2017-06-29T19:27:21.848624531Z url=self._url) 2017-06-29T19:27:21.848643245Z File "/root/docker_registry_frontend/registry.py", line 53, in json_request 2017-06-29T19:27:21.848662827Z DockerRegistry.string_request(*args, **kwargs) 2017-06-29T19:27:21.848681835Z File "/usr/lib/python3.5/json/__init__.py", line 319, in loads 2017-06-29T19:27:21.848701248Z return _default_decoder.decode(s) 2017-06-29T19:27:21.848720218Z File "/usr/lib/python3.5/json/decoder.py", line 339, in decode 2017-06-29T19:27:21.848739793Z obj, end = self.raw_decode(s, idx=_w(s, 0).end()) 2017-06-29T19:27:21.848758913Z File "/usr/lib/python3.5/json/decoder.py", line 357, in raw_decode 2017-06-29T19:27:21.848778466Z raise JSONDecodeError("Expecting value", s, err.value) from None 2017-06-29T19:27:21.848818943Z json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) 2017-06-29T19:27:21.848853634Z 127.0.0.1 - - [29/Jun/2017 19:27:21] "GET / HTTP/1.0" 500 -
Hello @brennerm
I got the next issue when I was trying to get a list of images:
Though I can see the repositories:
"docker logs -f reg-ui" shows following:
[2018-05-30 09:37:17,166] ERROR in app: Exception on /registry/registry-it/repo/iisserver [GET]
Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "frontend.py", line 137, in tag_overview
repo=urldecode_filter(repo))
File "/usr/local/lib/python3.6/site-packages/flask/templating.py", line 135, in render_template
context, ctx.app)
File "/usr/local/lib/python3.6/site-packages/flask/templating.py", line 117, in _render
rv = template.render(context)
File "/usr/local/lib/python3.6/site-packages/jinja2/asyncsupport.py", line 76, in render
return original_render(self, *args, **kwargs)
File "/usr/local/lib/python3.6/site-packages/jinja2/environment.py", line 1008, in render
return self.environment.handle_exception(exc_info, True)
File "/usr/local/lib/python3.6/site-packages/jinja2/environment.py", line 780, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.6/site-packages/jinja2/_compat.py", line 37, in reraise
raise value.with_traceback(tb)
File "/root/templates/tag_overview.html", line 1, in top-level template code
{% extends "layout.html" %}
File "/root/templates/layout.html", line 21, in top-level template code
<div id="content" class="container-fluid">{% block content %}{% endblock %}</div>
File "/root/templates/tag_overview.html", line 21, in block "content"
<td>{{ registry.get_size_of_layers(repo, tag) | to_mb }} MB</td>
File "/root/docker_registry_frontend/registry.py", line 97, in get_size_of_layers
result += self.get_size_of_layer(repo, image_id)
File "/root/docker_registry_frontend/cache.py", line 21, in decorator
result = f(*args, **kwargs)
File "/root/docker_registry_frontend/registry.py", line 337, in get_size_of_layer
method='HEAD'
File "/root/docker_registry_frontend/registry.py", line 64, in request
return urllib.request.urlopen(request, timeout=3)
File "/usr/local/lib/python3.6/urllib/request.py", line 223, in urlopen
return opener.open(url, data, timeout)
File "/usr/local/lib/python3.6/urllib/request.py", line 532, in open
response = meth(req, response)
File "/usr/local/lib/python3.6/urllib/request.py", line 642, in http_response
'http', request, response, code, msg, hdrs)
File "/usr/local/lib/python3.6/urllib/request.py", line 570, in error
return self._call_chain(*args)
File "/usr/local/lib/python3.6/urllib/request.py", line 504, in _call_chain
result = func(*args)
File "/usr/local/lib/python3.6/urllib/request.py", line 650, in http_error_default
raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 404: Not Found
127.0.0.1 - - [30/May/2018 09:37:17] "GET /registry/registry-it/repo/iisserver HTTP/1.0" 500 -
But "curl" returns the folowing:
curl http://192.168.36.37:5000/v2/iisserver/tags/list
{"name":"iisserver","tags":["base"]}
Docker version: 18.03.1-ce.
I was building an image from Dockerfile and running the prebuild image but I've got the same error in the both cases.
Could you help me? Thanks in advance.
Is it possible to define a context like
http://localhost:8080/docker-registry-frontend
It would be much easier to use the frontend behind a proxy like nginx.
Thanks
Where is about basic auth i can read?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.