What is Harbor?
Harbor, a CNCF graduated project (2020), is an OCI-compliant artifact repository system that stores not only container images but also Helm Charts, Open Policy Agent Bundles, WASM Modules, Tekton Pipelines, and more.
It serves as a powerful alternative to both paid and open-source container registries, including
DockerHub
AWS Elastic Container Registry
Azure Container Registry
Google Container Registry
Sonatype Nexus Repository
Jfrog Artifactory
Harbor lets you build two categories of projects:
Private – Images can only be pulled by members of a project.
Public – Anyone can pull images.
As a default, a public project with the title "Library" is set. There are no strict quotas defined per project, and quotas could be scaled out to unlimited capacity if required.
Harbor has other advanced capabilities such as:
Role-Based Access Control (RBAC) to safely manage users.
Vulnerability Scanning to identify security vulnerabilities.
Image Replication between multiple registries.
Audit Logs for monitoring and tracking all image-related operations.
These features render Harbor a solid option for artifact management in cloud-native ecosystems such as Kubernetes and Docker.
Why use Harbor over DockerHub?
DockerHub is one of the most popular image repositories but it has its own limitations as follows
Self-Hosting Flexibility – In contrast to DockerHub, which is hosted by Docker itself, Harbor can be self-hosted in on-premise and cloud environments such as AWS, GCP, and Azure.
Unlimited Private Repositories – The free tier in DockerHub restricts users to just 2 private repositories, while Harbor places no such limit on private repositories.
Comprehensive Audit Logs – DockerHub has no audit logging built into it, whereas Harbor keeps very detailed logs of all image-related operations.
Tailored for High-Frequency Pulls – High-pull frequency businesses enjoy Harbor's cost-effective, lag-free experience without slowdowns and additional fees.
Improved Image Replication – Harbor replicates images across multiple Harbor instances, DockerHub, AWS ECR, GCP GCR, Azure ACR, and others, while DockerHub doesn't have native replication capabilities.
Step-by-Step Installation Guide
Some Prerequisites
AWS Account
Foundational Docker Knowledge
Adding PORTS into the Inbound Rules in AWS
Curiosity to Learn
We will try to install it in the AWS EC2 Instance
# Consider the machine with the following configuration
name: harbor-server
OS: ubuntu 22.04 (Free Tier Eligible)
size: t3 micro
disk size: 10 GB # more than enough to get the demo running
# PORTS TO BE OPENED
HTTP: 80
HTTPS: 443
TCP PORT : 8086
Now let's get started with the installations for docker and docker-compose
# Switch to Root user
sudo su
# Update System
sudo apt update
# Install Docker and Docker Compose
sudo apt install docker.io docker-compose -y
# Start, Enable, Check Status of Docker
sudo systemctl start docker
sudo systemctl enable docker
# Install Unzip and Curl (as not installed by default)
sudo apt install unzip curl -y
We can now make a move toward installing the Harbor.
# Get and Download from the Link
wget https://github.com/goharbor/harbor/releases/download/v2.8.2/harbor-online-installer-v2.8.2.tgz
# Extract the Installer:
tar xzvf harbor-online-installer-v2.8.2.tgz
cd harbor
We will create a new file named harbor.yml (it will act as the source of truth for the installation) and copy the content from the harbor.yml.tmpl file(created by default).
cp harbor.yml.tmpl harbor.yml
# the harbor.yml.tmpl can be deleted
rm harbor.yml.tmpl
This is how our harbor.yml will span out
NOTE: We will be using the HTTP connection so we will comment on the part of HTTPS to minimize the confusion.
We are changing the HTTP default port from 80 to 8086; take reference here to avoid confusion.
hostname: <PUBLIC IP of HOSTNAME>
# http related config
http:
# port for http, default is 80. If https enabled, this port will redirect to https port
port: 8086 # we are manually changing the PORT from 80 => 8086
# https related config
#https:
# https port for harbor, default is 443
# port: 443
# The path of cert and key files for nginx
#certificate: /your/certificate/path
#private_key: /your/private/key/path
harbor_admin_password: Harbor12345
Now we need to make a change in the daemon.json file as accessing the Harbor via the HTTP Connection is considered as accessing the insecured registry so we need to manually add the entry to the daemon.json file.
NOTE: If daemon.json is not present then create it manually
# Path to the daemon.json file
cat /etc/docker/daemon.json
# If daemon.json not present then create it
nano /etc/docker/daemon.json
# Add the Content into the Json file
{
"log-level": "error",
"insecure-registries": ["<YOUR PUBLIC IP>:8086"]
}
Now restart the Docker Service
sudo systemctl restart docker
Then run the installable shell file present (under harbor folder)
sudo ./install.sh
Now we can easily access our Harbor Dashboard easily like
http://<PUBLIC IP OF HOST>:8086
The Default Credentials will be looking as
username: admin
password: Harbor12345 <# Recommended to Change it>
By default the library project(Public) is present, but we will create a new project named harbor-demo
Setting the Project Quota Limits as -1 indicates the unlimited quota set for the project.
Access level: By default is set to Private
Now we are all set with our basic project setup and we will move on to further steps.
Pushing the Docker Image to Harbor
Step 1. Pull some sample docker images from the docker hub (can also pull multiple like hello-world)
docker pull busybox
docker pull hello-world
# Check for the image
docker images
Step 2: Log in to the Harbor Registry
docker login <your-ip-or-domain>:port
Authenticating with existing credentials...
WARNING! Your password will be stored unencrypted in /root/snap/docker/2932/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
We need to use the username and password which we have set in the harbor.yml file
username: admin
password: Harbor12345
NOTE: If any problem persists then check the harbor.yml file for the configuration; following the previous steps as mentioned.
Step 3: Tag the Image
After logging in, you need to tag your Docker image with the Harbor registry information.
docker tag busybox:latest <YOUR_PUBLIC_IP>:8086/harbor-demo/busybox:latest
# Check if the image properly tagged
docker images
Step 4: Push the Image onto the Harbor Registry
docker push <YOUR_PUBLIC_IP>:8086/harbor-demo/busybox:latest
Step 5: Verify the Image pushed onto the harbor-demo project
Visit the Harbor Dashboard for this and check it out
Pulling the Image from Harbor
Consider a scenario where the Image is not available locally and we need to pull it from the Harbor Repository then we can do it as follows
docker pull <YOUR_PUBLIC_IP>:8086/harbor-demo/busybox:latest
Verify it at the local end it should be present
Conclusion
Harbor isn’t just another container registry—it’s a powerhouse for enterprises looking to break free from DockerHub’s limitations. With unlimited private repos, image replication, security scanning, and RBAC, it gives you complete control over your artifacts.
Whether you’re running Kubernetes or managing multi-cloud deployments, Harbor ensures speed, security, and flexibility—without the hassle of rate limits or vendor lock-in.
Survived this deep dive? Stay ahead—subscribe for the EzyInfra Knowledge Base for more DevOps wisdom.
EzyInfra.dev is a DevOps and Infrastructure consulting company helping clients in Setting up the Cloud Infrastructure (AWS, GCP), Cloud cost optimization, and managing Kubernetes-based infrastructure. If you have any requirements or want a free consultation for your Infrastructure or architecture, feel free to schedule a call here.
Share this post