Harbor + Kubernetes = Self-Hosted Container Registry
Tags: kubernetes, vcluster, devspace, loft
Published: 2022-06-16 18:50:34

By [Kasper Siig](https://twitter.com/kaspersiig)

Self-hosting is, by no stretch of the imagination, a new concept. For many years, engineers and IT admins have been looking into how they can self-host their tools. Primarily, it was because self-hosting was the only viable solution, as cloud providers hadn’t started gaining traction yet. However, even with the recent rise in popularity of said cloud providers, many still consider whether they should self-host.

[Harbor](https://goharbor.io/) is the solution if you want to self-host a container registry for Docker images. It was developed initially inside of VMware but has since been [adopted by CNCF](https://blogs.vmware.com/opensource/2018/07/31/cncf-adopts-project-harbor/). Today, it lives as an open-source tool, aiming to give users as many features as possible while still being free. In this tutorial, you’ll be shown how to get it up and running inside of [Kubernetes](https://kubernetes.io/).

## What Is Harbor?

In its essence, Harbor is a self-hosted container registry. This means that instead of relying on a provider, like GCP or Azure, to host your images, you can do it yourself. This keeps all your infrastructure internal and makes you less reliant on other sources. For many, this can be a valuable characteristic. Some organizations prefer hosting things themselves, but others—like the medical industry, being under [HIPAA](https://en.wikipedia.org/wiki/Health_Insurance_Portability_and_Accountability_Act) restrictions—*have* to host it themselves.

Besides making it possible to host your Docker registry yourself, Harbor also comes with a variety of other nice features, many of them related to improving security. With your images hosted in Harbor, you can set up [vulnerability scanning](https://goharbor.io/docs/2.0.0/administration/vulnerability-scanning/) to make sure that you are aware of all the vulnerabilities present in your images. This is accomplished via open-source projects [Trivy](https://github.com/aquasecurity/trivy) and [Clair](https://github.com/coreos/clair). You can use the severity levels to decide what images are allowed to be used, for example, restricting any images containing severe vulnerabilities. On top of that, Harbor also provides support for general supply chain security, signing images, and much more.

## Why Use Harbor?

While the features mentioned in the last section do sound like they add a lot to any deployment, you may still be wondering why you would want to use Harbor and not some other tool. Well, there are many reasons that underscore its value versus other tools. The first likely reason is that you want more control over your registry—you want the ability to configure it exactly to your liking. While many providers do offer a lot of configuration, you are often stuck with the way of deployment the provider offers. With a self-hosted solution, you’re the one deciding how things are getting deployed.

You may also find Harbor to have some features that you can’t find anywhere else. For example, it’s not uncommon to have separate registries for dev, QA, and prod. This can be done via Harbor as well, but Harbor also makes it easy to manage them cohesively. It even offers the ability to sync images between repositories, giving you a straightforward way to promote images through the different deployment stages. Now, read on to learn how you can get it running.

## Setting Up Harbor

Before you start setting up Harbor, make sure you have all the prerequisites:

* [Kubectl](https://kubernetes.io/docs/reference/kubectl/kubectl/) for managing your cluster
* [Helm](https://helm.sh/) 3 for installing Harbor
* [Minikube](https://minikube.sigs.k8s.io/docs/) as the creation tool for a local Kubernetes cluster
* [VirtualBox](https://minikube.sigs.k8s.io/docs/drivers/virtualbox/) as the driver for minikube

### Installing Harbor

In a typical production scenario, you will be running your Kubernetes cluster on something like GCP or AWS, but that is fairly heavy for a tutorial. Here, you’ll be using minikube; a tool meant to spin up Kubernetes clusters locally. With minikube installed, start a new cluster by running the following command:

```bash
$ minikube start --vm-driver virtualbox
```

This will take a while, but you’ll have a running Kubernetes cluster when the command is done. At this point, you’ll want to enable the ingress add-on so you can access your Harbor installation, so run this:

```bash
$ minikube addons enable ingress
```

By now, you should have everything configured in minikube. Next, you will work to install the Helm chart for Harbor, but you will first need to add the repository to Helm:

```bash
$ helm repo add harbor https://helm.goharbor.io
```

With the repository added, you can install the Helm chart by running the following:

```bash
$ helm install my-release harbor/harbor
```

At this point, you’ll need to wait for all the pods to get into a running state. Check this by running `kubectl get pods`. You may see that some of them are failing, which will happen, as they depend on each other. You will likely need to wait at least fifteen to twenty minutes for them to be ready. Once they’re running, run `minikube ip` to get the IP address of your minikube cluster.

You now need to use this IP to change your `/etc/hosts` file. The default URL for Harbor is `https://core.harbor.domain`, but you need to make sure that when this is typed into the address bar of your browser, it resolves to your cluster. Do so by entering the following two new lines into your `/etc/hosts` file:

```bash
<ip-of-minikube>	core.harbor.domain
<ip-of-minikube>	notary.harbor.domain
```

Now you should be able to go to https://core.harbor.domain and log in using the default username and password:

```
username: admin
password: Harbor12345
```

![Harbor login screen](https://loft.sh/blog/images/content/kasper-siig-harbor-login.png)

### Configuring the Docker Client

At this point, you have an active Harbor installation that you can start to use. However, that does not mean you are ready to use it as a registry. You still need to install the Harbor certificates to ensure that communication between your PC and the registry doesn’t get blocked.

First, you need to configure the Docker daemon to use the one in minikube. Assuming you are running either Linux or OSX, you can run this:

```bash
$ eval $(minikube docker-env)
```

This will configure your environment variables to point to the minikube Docker daemon. Next, you need to get the certificates from the Kubernetes Secrets:

```bash
kubectl -n harbor get secrets harbor-ingress -o jsonpath="{.data['ca\.crt']}" | base64 -D > harbor-ca.crt
```

> Note that this uses `base64 -D`, whereas, on Linux, it would use `base64 -d`.

At this point, you have a `harbor-ca.crt` file containing the certificate. To get it installed in the Docker daemon, you’ll need to first copy the certificates into the minikube VM:

```bash
$ scp -o IdentitiesOnly=yes -i $(minikube ssh-key) harbor-ca.crt docker@$(minikube ip):./harbor-ca.crt
```

Once the certificate is copied over, you can install the certificate by logging into the minikube VM and installing it:

```bash
$ minikube ssh
$ sudo mkdir -p /etc/docker/certs.d/core.harbor.domain
$ sudo cp harbor-ca.crt /etc/docker/certs.d/core.harbor.domain
```

Finally, run `exit` to get back to your normal terminal. At this point, the certificates are installed, and you can now test that everything is working as expected by logging in and pushing an image:

```bash
# Log into the registry
$ docker login core.harbor.domain --username=admin --password Harbor12345

# Pull an image from Docker Hub
$ docker pull nginx

# Tag the image, so it's ready to be pushed
$ docker tag nginx core.harbor.domain/library/nginx:latest

# Push the image to the registry
$ docker push core.harbor.domain/library/nginx:latest
```

## Conclusion

If you have reached this point successfully, you now have an active installation for Harbor, and you can start using it as your very own private registry. This allows you to have complete control over your registry and the way it’s deployed. On top of that, you get all the available features in this open-source tool, like vulnerability scanning and image replication. Rather than reading through lists of all the features, you can test out the tool for yourself and get a feeling for exactly how you can use it.

Whatever your reasons for running a private registry, you now know how it’s done. From here, you can more appropriately compare the two scenarios of self-hosting versus a managed solution. Figure out what advantages a self-hosted solution gives you and whether they outweigh the disadvantages of a managed one.

*Photo by [Cameron Venti](https://unsplash.com/@ventiviews?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/containers?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)*