Harbor Overview
What is Harbor?
Harbor is an open-source container registry designed for storing, managing, and securing container images and other OCI artifacts. In simple terms, it gives teams a private place to push, organize, scan, and pull the images they use to deploy applications.
Harbor sits in the artifact and registry layer of the stack. It is the system that holds the images your Kubernetes clusters, application teams, and CI/CD pipelines depend on.
Why Harbor matters
- Store and organize container images in a private registry
- Control who can push, pull, or manage artifacts
- Scan images for vulnerabilities
- Apply retention and governance policies
- Support secure deployments into Kubernetes environments
Where Harbor fits in the stack
A simple way to think about Harbor is: CI/CD builds the image, Harbor stores and scans the image, and Kubernetes pulls the approved image into the runtime environment.
- Build systems and CI pipelines create the image
- Harbor stores, scans, and governs the image
- Kubernetes clusters pull approved images for deployment
Core features
Private image registry
Harbor stores container images in a controlled private registry instead of relying only on public registries.
RBAC and project-based access
Harbor lets teams organize artifacts into projects and control access by role.
Vulnerability scanning
Harbor can integrate with scanners such as Trivy to identify known vulnerabilities in stored images.
Replication and lifecycle control
Harbor supports artifact replication and retention policies for storage management.
Secure deployment support
Harbor supports signed artifacts, access control, and controlled pull access for Kubernetes and delivery pipelines.
Assumptions
- Harbor is being used primarily as a private OCI/container registry
- Kubernetes is the main deployment target
- Helm is the preferred deployment method
- Trivy is the image scanner when vulnerability scanning is enabled
- TLS and ingress are expected in production environments
Deployment Runbook
This runbook focuses on deploying Harbor into Kubernetes using Helm. It is command-first and optimized for practical rollout, validation, and debugging.
Step 1 — Prepare prerequisites
Run:
kubectl version --client
helm version
docker version
- Confirm you have a Kubernetes cluster, Helm 3, Docker, ingress, storage, DNS, and a TLS strategy.
- Decide whether Harbor will use internal or external PostgreSQL, internal or external Redis, and PVCs or object storage.
Step 2 — Add the Harbor Helm repository
Run:
helm repo add harbor <https://helm.goharbor.io>
helm repo update
helm search repo harbor/harbor --versions | head
Step 3 — Create the namespace
Run:
kubectl create namespace harbor
Step 4 — Create a values file
Create harbor-values.yaml with the minimum production-relevant settings.
Adjust storage, ingress class, hostname, and secrets for your environment.
Step 5 — Prepare TLS
Step 6 — Install Harbor with Helm
Run:
Step 7 — Check pods and services
Run:
kubectl get pods -n harbor
kubectl get svc -n harbor
kubectl get ingress -n harbor
Expect Harbor core, portal, registry, jobservice, trivy, database, and redis to come up cleanly.
Step 8 — Validate Harbor UI access
Run:
kubectl get ingress -n harbor
- Open https://harbor.example.com and confirm the UI loads, TLS is valid, and login works.
Step 9 — Create a test project
- Log in as admin
- Create a project such as demo
- Decide whether the project should be private or public
Step 10 — Test Docker login
Run:
docker login harbor.example.com
Step 11 — Test image push
Run:
docker pull nginx:latest
docker tag nginx:latest harbor.example.com/demo/nginx:latest
docker push harbor.example.com/demo/nginx:latest
Step 12 — Test image pull
Run:
docker pull harbor.example.com/demo/nginx:latest
Step 13 — Validate vulnerability scanning
- Open the pushed image in the Harbor UI
- Confirm Trivy scan results appear
- Review severity findings
Step 14 — Configure Kubernetes pull access
Run:
Step 15 — Validate Kubernetes image pull
Run:
kubectl get pods -n <your-namespace>
kubectl describe pod <pod-name> -n <your-namespace>
- Success looks like a healthy pod with no ErrImagePull or ImagePullBackOff.
Step 16 — Validate CI/CD integration
Run:
docker build -t harbor.example.com/demo/my-app:build-001 .
docker push harbor.example.com/demo/my-app:build-001
- Make sure CI stores registry credentials securely and uses consistent image tagging.
Deployment notes
- PVCs are simpler for initial deployments; object storage is often better for larger production registry storage.
- Use an external PostgreSQL database if your organization standardizes on managed databases or wants stronger backup and restore control.
- Use TLS in production from day one if possible. Harbor is a credentials-bearing system and should be treated like a secure internal platform service.
Administration & Best Practices
Organize Harbor by projects
Use projects as the main management boundary. Good separation patterns include by team, by product, by environment, or by trust boundary.
Use RBAC intentionally
- Give push rights only where needed
- Separate admin responsibilities from daily developer access
- Avoid broad write access across unrelated projects
Enable and review vulnerability scanning
- Make sure scans are actually running
- Review severe findings
- Define internal expectations for handling high-risk images
Standardize image tagging
- Use semantic version tags, build numbers, git SHA tags, or promoted environment tags
- Avoid relying only on latest in production workflows
Manage storage growth
- Plan for artifact retention
- Clean up unused tags
- Monitor storage
- Review large repositories periodically
Use TLS everywhere in production
Harbor handles credentials and deployment artifacts. Treat it as a secure platform service.
Validate pull paths from the real runtime
- Do not stop at UI success
- Always validate Docker login, push path, pull path, and Kubernetes pull behavior
Troubleshooting & FAQ
Harbor UI does not load
- Check ingress, DNS, TLS, Harbor pods, and ingress controller health
kubectl get ingress -n harbor
kubectl get pods -n harbor
kubectl describe ingress -n harbor
kubectl logs -n harbor deploy/harbor-core
Docker login fails
- Check the Harbor hostname, credentials, TLS trust, ingress routing, and Harbor core availability
docker login harbor.example.com
kubectl logs -n harbor deploy/harbor-core
kubectl logs -n harbor deploy/harbor-portal
Image push fails
- Check repository path, project existence, push permission, registry health, and writable storage
docker push harbor.example.com/demo/nginx:latest
kubectl get pods -n harbor
kubectl logs -n harbor deploy/harbor-registry
Kubernetes cannot pull images
- Common symptoms include ErrImagePull and ImagePullBackOff
- Check imagePullSecret, credentials, namespace, image path, and cluster reachability to Harbor
kubectl get secret harbor-pull-secret -n <namespace>
kubectl describe pod <pod-name> -n <namespace>
kubectl get events -n <namespace> --sort-by=.metadata.creationTimestamp
Scan results do not appear
- Check that Trivy is enabled and the trivy and core pods are healthy
kubectl get pods -n harbor
kubectl logs -n harbor deploy/harbor-trivy
kubectl logs -n harbor deploy/harbor-core
Storage fills up too quickly
- Review retention policies, old tags, duplicate images, and large repositories
- Clean unused artifacts and consider moving to object storage if growth requires it
When should we use external DB or object storage?
Use external services when you want stronger backup and restore workflows, need to scale beyond a simple default setup, or already standardize on managed services. For small or early deployments, internal DB plus PVCs is usually simpler.

