Create your own docker private registry without GUI simplest way

Vineet Kumar
4 min readJan 14, 2022

This story describes how you can easily set up a local or externally accessible Docker registry for hosting your own built Docker images.

First method (Basic Registry) show registry configurations that are only appropriate for testing (also explain gotchas in this basic registry configuration). A production-ready registry must be protected by TLS and should ideally use an access-control mechanism. For production setup you can follow only Last method to create registry server

Prerequisite:
Before you can deploy a registry, you need to install Docker on the host. A registry is an instance of the registry image, and runs within Docker.

Method I: Running a Docker registry :
You can start with running the provider docker registry image from Docker hub for a minimal Docker registry setup. This will start an HTTP version of the server without access control accessible on port 5000.

docker run -d -p 5000:5000 --restart=always --name registry registry:2

Once the registry image has been pulled and is up and running on your machine, you are ready to push your built images to it. Prefix your image tag with your host and port localhost:5000 whenever you tag or push to that registry.
For example if u want to pull and push nginx latest image then use following commands

$ docker pull nginx
$ docker image tag nginx localhost:5000/nginx-test
$ docker push nginx:5000/nginx-test

Gotcha (Cons) :
If you get the following error when trying to push to your HTTP registry, you will need to do some configuration to work around a security restriction for registries to be HTTP only unless the hosts are whitelisted for the docker daemon.

$ docker push localhost:5000/nginx-test 
Error response from daemon: Get https://localhost:5000/v2/: http: server gave HTTP response to HTTPS client

to work around this error for local testing we can configure our Docker daemon to allow for HTTP connection to our local Docker registry that is running. You will want to configure your Docker daemon.json file (resides under /etc/docker/daemon.json if not available then create it and copy following content ) with the following config and restart the docker service (systemctl restart docker ) on your machine to have the settings take effect.

{
"insecure-registries" : ["localhost:5000"]
}

if want to access this registry from remote machine then also follow the above steps mentioned for daemon.json file

Now finally push your image to local repository

$ docker push localhost:5000/nginx-test

To check Image is available or not, use the following commands

Use curl command in CLI:
To get a list of repositories pushed on the private registry:
curl <host_ip>:<docker_host_port>/v2/<repository_name>/tags/list
To get a list of images pushed on the private registry
curl <docker_host_ip>:<docker_host_port>/v2/_catalog

METHOD II: Run an externally-accessible registry on 80,443 port
Prerequisites:
You should have already obtained a certificate from a certificate authority (CA).
You should configure TLS for any externally accessible Docker registry to assure the consumer of your images that the image data they are received is coming from who they expected it to be. Setting this up is nice and easy with the Docker registry image, mount your .crt and .key file that you might generate with a tool like cerbot into the image and assign the REGISTRY_HTTP_TLS_CERTIFICATE and REGISTRY_HTTP_TLS_KEY environment variables to the paths of your domains certificate (In given example it is certs directory which will create where following docker command will run)and keys inside the container. In given Example

$ docker run -d --restart=always --name registry -v "$(pwd)"/certs:/certs -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/ca.crt -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key   -p 443:443 -p 80:80 registry:2

Once the image is up and running, you will be able to push and pull from the registry by using your domain for the registry host to push and pull images from

$ docker pull nginx
$ docker tag node myregistry.domain.com/nginx
$ docker push myregistry.domain.com/nginx
$ docker pull myregistry.domain.com/nginx

To access this private registry server from remote machine do host entry in remote machine with egress IP. Now open the browser and run following command to check images and its tag

https://<host_ip>:<docker_host_port>/v2/<repository_name>/tags/list
https://<docker_host_ip>:<docker_host_port>/v2/_catalog

PROS:
This setup will not trigger the same HTTP error as earlier requiring the whitelisting of the registry host and is thus the recommended method to have your Docker registry serve its images to your users
CONS: There is no authentication for registry server so anyone can use these registry server so not it for production environment.

Method III : Externally-accessible Docker registry with access control for production environment

Step I:
Now, if you would like to restrict who can and can’t write to your docker registry, you can force users to log in to your registry before reading or writing to it. Users and their passwords to the registry in its most simple form are handled in a htpasswd format. You can generate the password file for your users by using the following command and container switching out your user and password as needed for your use case (Also create without run following docker command)

docker run --entrypoint htpasswd httpd:2 -Bbn testuser testpassword > auth/htpasswd

STEP II:

With this password file generated for your users, you can mount the file into your Docker registry container and configure the REGISTRY_AUTH_HTPASSWD_PATH environment variable to point to this password file inside the container. You should also configure the REGISTRY_AUTH and REGISTRY_AUTH_HTPASSWD_REALM environment variables for basic auth like in the snippet below (Which is similar to METHOD II docker command only authentication is adding).

$ docker run -d --restart=always --name registry -v "$(pwd)"/certs:/certs -v "$(pwd)"/auth:/auth  -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/ca.crt -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key   -p 443:443 -p 80:80 registry:2

Step III : pull and push images

$ docker pull nginx
$ docker tag node myregistry.domain.com/nginx:v2
$ docker login myregistry.domain.com (Inject login username and password as mentioned in above command)
$ docker push myregistry.domain.com/nginx:v2
$ docker pull myregistry.domain.com/nginx:v2

STEP IV: Check Push images and its tags on browser by using following urls after entering the authentication

https://<host_ip>:<docker_host_port>/v2/<repository_name>/tags/list
https://<docker_host_ip>:<docker_host_port>/v2/_catalog

ENJOY!!!

--

--