Self-hosted Docker Registry and Web-UI with HTTPS support

Windix Feng
3 min readSep 22, 2024

--

Why? I want to host and run some private docker images on my Unraid NAS.

For Docker Registry, it is a no-brainer that we can use the official one (docker hub link).

On Unraid, this is the existing docker app “DockerRegistry”. Once installed and started, it listens on port 5000.

Now we have two issues need to be sorted out:

  1. Both docker cli and Unraid docker doesn’t like registry on HTTP (server gave HTTP response to HTTPS client)
  2. Docker Registry doesn’t comes with web UI. We would be lost really soon on what are there in this registry.

Here is what I found for reference.

Update 28/09/2024: It turns out that adding HTTPS support is NOT that difficult. So you no longer need this section.
Please see the new 3rd section for details. Still keeping this section for reference

To allow docker cli talking to registry on HTTP, need to add insecure-registries option to docker daemon.

In below examples, I am referring to my HTTP docker registry as 192.168.88.77:5000

On Ubuntu Linux:

$ cat /etc/docker/daemon.json 
{"insecure-registries":["192.168.88.77:5000"]}

On Unraid NAS (source):

# cat /boot/config/docker.cfg
...
DOCKER_OPTS="--insecure-registry 127.0.0.1:5000"

# /etc/rc.d/rc.docker restart

Refer to this for other OS.

For a just-work web UI, I found this one written in Go: https://github.com/genuinetools/reg

Last update was in 2019, but still works perfectly. If you want something heavy / enterprise level, try https://github.com/goharbor/harbor

I wrote a wrapper Dockerfile to make it listening on port 5001:

FROM 192.168.88.77:5000/reg:latest

ENV REGISTRY_URL=192.168.88.77:5000

EXPOSE 5001

# override the entrypoint from base image
ENTRYPOINT []

CMD ["/bin/sh", "-c", "reg server --registry ${REGISTRY_URL} --port 5001 --force-non-ssl"]

Works perfectly:

This section has been added on 28/09/2024 for HTTPS setup.

It is trivial to add HTTPS support with an HTTPS proxy solution (e.g. I am using Nginx Proxy Manager aka NPM in below examples).

Assume you have already both docker registry and UI running.

Just to recap:

  • Docker registry listens on 192.168.88.77:5000 (in HTTP mode). The actual registry API is behind http://192.168.88.77:5000/v2/
  • The registry UI (reg) listens on 192.168.88.77:5001

Also as pre-requisite, you need to get an HTTPS certificate. I will skip this part. Assume you have sorted it out in NPM already. My domain name / certificate is docker.example.com

(You may ask then you are exposing your private registry to public. No I didn’t. I have a custom local DNS entry to resolve docker.example.com to local IP)

For step 2 above, you also need to modify Environment Variable with a new value docker.example.com . In my case I just updated the original Dockerfile:

ENV REGISTRY_URL=docker.example.com

Note that we no longer need to specify port number 5000 since it defaults to port number 443 (HTTPS) now.

Create a new proxy host in NPM:

Then in “SSL” tab select your earlier docker.example.com certificate.

Once this is done, you get a nice and clean setup:

  • Access https://docker.example.com shows you the registry UI
  • Anywhere you can refer your registry to docker.example.com/image:version
  • You also no longer need any hack for insecure registry mentioned in section 1.

Also just a quick reference on how to push to private registry:

docker build . -t my-image:latest

docker tag my-image:latest docker.example.com/my-image:latest

docker push docker-example.com/my-image:latest

--

--

No responses yet