How to Setup Private Docker Registry on Ubuntu 20.04

In this post, we are going to learn how to setup private docker registry on Ubuntu 20.04.

Why Private Docker Registry ?

For Smooth CI/CD development using the docker platform, consider using a self-hosted docker registry server. Docker registry is the repository where you can store your docker images and pull them to run applications on the server. For faster delivery as well as secure infrastructure, it is recommended to set up your own docker private registry to store your docker images and distribute among organizations.

Prerequisites

  • User account with sudo privileges
  • A server for Docker registry
  • Nginx on the Docker Registry server
  • A client server
  • Docker and Docker-Compose on both servers.

What is Private Docker Registry?

Docker Registry is a Server-side application which allows you to store your docker images locally into one centralized location. By setting up your own docker registry server, you can pull and push docker images without having to connect to the Docker hub, saving your bandwidth and preventing you from security threats.

Also Read : How to Install Docker on Ubuntu 22.04 / 20.04 LTS

Before You start

Before starting, I ensure that you have installed Docker and Docker-Compose on both client server and local registry server. To verify you have installed required software, you can run the following commands to check the software version.

$ docker version

docker-version-output-linux

$ docker-compose version

docker-compose-version-output-linux

Also, you need to ensure that docker service is started and is setup to enable at boot time:

$ sudo systemctl start docker
$ sudo systemctl enable docker

Install and Configure Private Docker Registry

To configure Private Docker Registry, follow the steps:

Create Registry Directories

Configure your server that is going to host a private registry. Create a new directory that will store all the required configuration files.

Use the following command to create a new project directory ‘my-registry’ and two sub directories ‘nginx’ and ‘auth’. You can have your own assumption for the project name.

$ mkdir -p my-registry/{nginx, auth}

Now navigate to the project directory and create new directories inside nginx as:

$ cd my-registry/
$ mkdir -p nginx/{conf.d/, ssl}

Create Docker-Compose script and services

You need to create a new docker-compose.yml script that defines the docker-compose version and services required to set up a private registry.

Create a new file “docker-compose.yml” inside “my-registry” directory with vi editor.

$ vi docker-compose.yml

Define your service in the docker-compose file as:

services:
#Registry
  registry:
    image: registry:2
    restart: always
    ports:
    - "5000:5000"
    environment:
      REGISTRY_AUTH: htpasswd
      REGISTRY_AUTH_HTPASSWD_REALM: Registry-Realm
      REGISTRY_AUTH_HTPASSWD_PATH: /auth/registry.passwd
      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
    volumes:
      - myregistrydata:/data
      - ./auth:/auth
    networks:
      - mynet

#Nginx Service
  nginx:
    image: nginx:alpine
    container_name: nginx
    restart: unless-stopped
    tty: true
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/conf.d/:/etc/nginx/conf.d/
      - ./nginx/ssl/:/etc/nginx/ssl/
    networks:
      - mynet

#Docker Networks
networks:
  mynet:
    driver: bridge

#Volumes
volumes:
  myregistrydata:
    driver: local

Save and close the file

Setup nginx Port forwarding

We need to create nginx virtual host configuration for nginx web service. Go to nginx/conf.d/ directory created in the above step.

$ cd nginx/conf.d/

Now create a nginx virtual host file with your text editor. In this example I am going to name it myregistry.conf. You can have your own assumption.

$ vi myregistry.conf

Add the following contents:

upstream docker-registry {
    server registry:5000;
}
server {
    listen 80;
    server_name registry.linuxtechi.com;
    return 301 https://registry.linuxtechi.com$request_uri;
}
server {
    listen 443 ssl http2;
    server_name registry.linuxtechi.com;
    ssl_certificate /etc/nginx/ssl/certificate.crt;
    ssl_certificate_key /etc/nginx/ssl/private.key;
    # Log files for Debug
    error_log  /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    location / {
        if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" )  {
            return 404;
        }
        proxy_pass                          http://docker-registry;
        proxy_set_header  Host              $http_host;
        proxy_set_header  X-Real-IP         $remote_addr;
        proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header  X-Forwarded-Proto $scheme;
        proxy_read_timeout                  900;
    }
}

Replace your domain name with server_name parameter and save the file.

Increase nginx file upload size

By default, nginx has a 1mb limit to upload files. As docker images exceed this limit, you need to increase the upload size in nginx configuration file. In this example, I am going to create an extra nginx configuration file with a 2GB upload limit .

Go to nginx configuration directory

$ cd myregistry/nginx/conf.d
$ vi additional.conf

Add the following line and save the file

client_max_body_size 2G;

Configure SSL certificate and Authentication

After creating nginx configuration file, now we need to set up an ssl certificate . You should have a valid ssl certificate file with a private key. Copy your certificate file and private key to nginx/ssl directory as:

$ cd myregistry/nginx/ssl
$ cp /your-ssl-certificate-path/certificate.crt .
$ cp /your-private-key-path/private.key .

If you do not have a valid purchased ssl certificate, you can generate your own self signed ssl certificate. Remember that a self signed ssl certificate is not recommended for production environments. To generate self signed ssl certificate, run the following command:

$ sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout \
 /etc/ssl/private/nginx-private.key -out /etc/ssl/certs/nginx-certificate.crt

You will be asked to submit some details like, Country code, domain name, email id. Fill up the details and continue.

Now setup Basic authentication as:

Go to auth directory

$ cd auth

Request a new password file named registry.password for your user. In this example I am going to use linuxtechi user.

$ htpasswd -Bc registry.password linuxtechi

If you get ‘htpasswd not found command‘, run the following command in your terminal and try again.

$  sudo apt install apache2-utils -y

Type a strong password and enter again to confirm your password. You have added a basic authentication user for docker registry.

Run Docker Registry

You have completed setup. You can build registry using docker-compose command.

Go to the directory, where we create docker-compose.yml file

$ cd myregistry

Now run the following command:

$ docker-compose up -d

Docker registry is now up, you can verify the running containers using following command:

$ docker ps -a

You will get following output:

docker-ps-a-command-output-linux

Pull Image from Docker Hub to a Private registry

To store an image from Docker hub to private registry, use docker pull command to pull docker images from docker hub. In this example, I am going to pull docker image of centos.

$ docker pull centos

After successfully pulling images from docker hub, tag an image to label it for private registry.

In this example, I am going to tag centos images as : registry.linuxtechi.com/linuxtechi-centos

$ docker image tag [image name] registry.linuxtechi.com/[new-image-name]

Example:

$ docker images tag centos registry.linuxtechi.com/linuxtechi-centos

To check if docker image is locally available or not , run the following command.

$ docker images

Push docker image to private registry

You have pulled docker image from docker hub and created a tag for private registry. Now you need to push local docker image to private registry.

Firstly, Login to your private registry using following command:

$ docker login https://registry.linuxtechi.com/v2/

Use your own registry url in the place of ‘https://registry.linuxtechi.com’

You will be prompted for username and password; you will get login successful message as:

docker-login-private-registry-linux

Now you can push your docker image to a private registry. To push image run the following command:

$ docker push registry.linuxtechi.com/linuxtechi-centos

Replace your image name after ‘docker push’

Once push is completed, you can go to browser and enter the url:

https://registry.linuxtechi.com/v2/_catalog

Replace registry.linuxtechi.com with your own url and provide basic authentication. You will find repositories list as :

docker-private-registry-gui-linux

Pulling docker image from Private Registry

You have pushed your local docker image to your private docker registry. In the same way you can pull docker images from your docker private registry to the local server.

Run the following command to login in your private registry server.

$ docker login https://registry.linuxtechi.com

Replace registry.linuxtechi.com with your own private registry url and provide basic authentication. Once the login is successful, run the following command to pull the docker image from private registry. In this example, I am going to pull previously pushed docker image in the local server. You can have your own assumption for docker image name.

$ docker pull registry.linuxtechi.com/linuxtechi-centos

You will have output similar as:

docker-pull-image-private-registry-linux

Conclusion:

In the article you have learned about how to host your own private docker registry. Also you got idea about how to pull images from docker hub to local server, tag the image and push into private registry. You have also learned how to pull docker images from private registry in the local server.

Also Read : How to Install KVM on Ubuntu 20.04 LTS Server (Focal Fossa)

2 thoughts on “How to Setup Private Docker Registry on Ubuntu 20.04”

  1. Great guide but I found a small typo, the compose file has

    REGISTRY_AUTH_HTPASSWD_PATH: /auth/registry.passwd

    but then you create the htpasswd file as registry.password

    needs to be
    htpasswd -Bc registry.passwd linuxtechi

    docker log:
    msg=”error checking authorization: stat /auth/registry.passwd: no such file or directory”

  2. ERROR: The Compose file ‘./docker-compose.yml’ is invalid because:
    Unsupported config option for networks: ‘mynet’
    Unsupported config option for volumes: ‘myregistrydata’
    Unsupported config option for services: ‘registry’

    Not working 🙁

Leave a Comment

Your email address will not be published. Required fields are marked *