How to Install Kubernetes Private Image Registry: Harbor

Written by: Bagus Facsi Aginsa
Published at: 30 Mar 2022

Kubernetes doesn’t have an image registry out of the box. So, the option is either to use the docker hub or install your own private image registry. Harbor is one of the CNCF Graduated projects that can be used as your private image registry for the Kubernetes cluster.

Harbor can be installed on Kubernetes Cluster directly, but I recommend you to install it outside the Kubernetes cluster.

Let’s see more detail on how to install and use it.


  1. Ubuntu server with a minimum spec of 2 CPU, 4GB RAM, and 40GB Disk Storage.
  2. Root Privileges, we need this privilege to install and configure Harbor on the server. Before starting, make sure to execute sudo su so we don’t have a permission issue.
  3. SSL certificate & Key.

Install Docker Engine

First, update our repository & Install docker dependencies

apt update && apt install ca-certificates curl gnupg lsb-release

Add Docker’s GPG Key

curl -fsSL | apt-key add -

Add Docker’s repository

add-apt-repository "deb [arch=amd64] focal stable"

Install Docker Engine using the package manager

apt update && apt install docker-ce docker-ce-cli

Docker will be installed in a few seconds. After the installation is done, check the Docker status

service docker status

Test your Docker Engine Installation by running docker hello world

docker run hello-world

If the Docker is installed correctly, it should be returning this kind of text

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:bfea6278a0a267fad2634554f4f0c6f31981eea41c553fdf5a83e95a41d40c38
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:

For more examples and ideas, visit:

Install Docker Compose

Docker Compose is another package that is mandatory to run Harbor.

Download the current latest stable docker-compose binary

curl -L "$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

Give executable permission to the docker-compose binary

chmod +x /usr/local/bin/docker-compose

Test the docker-compose installation

docker-compose --version

Install and Configure Harbor

Before installing the Harbor, go to the Harbor release page and find the version you want to download.

Right now, the latest release is v2.4.2, so I will download it here in this tutorial


Extract the installer package

tar xzvf harbor-online-installer-v2.4.2.tgz

Go to the extracted folder

cd harbor

Create a configuration file by Copy the template

cp harbor.yml.tmpl harbor.yml

Open the configuration file

nano harbor.yml

You need to edit some parameters inside the configuration file, find these parameters, and change them to suit your need.

First, find hostname parameter. Change the hostname value to match your domain name, in my case i will use


Next, find the https parameter. Upload your SSL certificate & Key, and then change the value of certificate and private_key value to match your SSL certificate & Key exact location on the server. In my case, both is in the /etc/ssl folder.

  # https port for harbor, default is 443
  port: 443
  # The path of cert and key files for nginx
  certificate: /etc/ssl/
  private_key: /etc/ssl/

Next, find the external_url parameter. Uncomment the parameter and change the url matching your domain name, in my case I will use


Lastly, check out the harbor_admin_password parameter. You don’t have to change the value, but remember this value because later we will use it when doing a first-time login to the Harbor GUI dashboard.

Save and exit, and then install the Harbor


The command above will check the prerequisite and download all the required images to run Harbor. After a few seconds (depending on your network), you will get a success message like this

Creating harbor-log ... done
Creating redis         ... done
Creating registry      ... done
Creating harbor-portal ... done
Creating harbor-db     ... done
Creating registryctl   ... done
Creating harbor-core   ... done
Creating harbor-jobservice ... done
Creating nginx             ... done
✔ ----Harbor has been installed and started successfully.----

Now, you should be able to access the Harbor GUI dashboard on your defined external_url, in my case it is Open your browser and go to the Harbor GUI dashboard.

Harbor Login Page

Log in using the username admin and the password matching the harbor_admin_password value on the Harbor configuration.

Security first, let’s change the admin password. Click the profile menu on the top right, and then click change password.

Harbor Profile Menu

After that, change the password.

Change Admin password on Harbor

After changing the password, let’s make a project. A project is needed to store the image that will be pushed to the Harbor. Go to the Projects menu, and then click the + NEW PROJECT button.

Click NEW PROJECT button on the Projects Menu

Give the project a name, in my case, superweb project, and set the project storage quota that suits your project need.

Create new project on Harbor GUI dashboard

Click OK.

After that, you will see the project is added to the dashboard

The created project appear on the Harbor GUI dashboard

The Harbor Installation & Configuration is done! Now you should be able to use the Harbor as your private image registry. To demonstrate how it works, we will show you how to push and pull images from the Harbor.

Push Image to Harbor

To push an image to the registry, first, you must log in to your registry via docker command line

docker login is my domain name, change it to your registry domain name. Type the username and password the same as we use on the Harbor GUI dashboard.

You will see the success message

Username: admin
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See

Login Succeeded

After that, you must build an image with this format


In my case, I will create an image named custom-nginx, here is how I build the image

docker build -t . is my registry domain name.

superweb is the project name we set earlier on the Harbor GUI dashboard.

custom-nginx is the image name

If the format is correct, you can push the image using this command.

docker push

Pull Image from Harbor

To Pull the image from the private registry, first, we need the create a secret containing the private registry credential.

Create a secret object with docker-registry type.

kubectl create secret docker-registry myprivateregistry --docker-username=admin --docker-password=XXXXXXXXX

You can change the secret name by changing the myprivateregistry value. Also, change the other marked parameter value to match your registry domain, username, and password.

This is a pod definition file example if you want to pull an image from the private registry.

apiVersion: v1
kind: Pod
  name: mypod
  - name: my-pod
  - name: myprivateregistry

Change the secret name, matching the secret you created earlier.

That’s it! Now you have your own private image registry for your Kubernetes Cluster.