Skip to content
Français
Account: not signed in, sync available My learning
Select theme
Français

Harbor: the image registry for DevSecOps teams

By updated

Improve this page

Harbor logo

This guide shows you how to install and use Harbor to store your container images, automatically scan for vulnerabilities and avoid Docker Hub rate limiting problems. You will learn to deploy Harbor with Docker Compose, configure the proxy cache to cache Docker Hub, and create robot accounts for your CI/CD pipelines. Prerequisite: a Linux server with Docker installed.

What you will learn

  • Decide when to choose Harbor rather than Pulp, Nexus or Artifactory
  • Install Harbor in production with HTTPS
  • Understand the architecture and the key features
  • Configure the proxy cache for Docker Hub (to avoid rate limiting)
  • Create robot accounts for your CI/CD pipelines
  • Automatically scan images with Trivy
  • Replicate images between several registries

What is Harbor?

Harbor is an open source cloud-native artifact registry, initially developed by VMware and now a CNCF graduated project (the highest maturity level). Think of Harbor as a private Docker Hub hosted in your own infrastructure, with built-in security features.

Why not use Docker Hub directly?

Docker Hub, the default public registry, raises several problems in an enterprise:

ProblemImpactHarbor solution
Rate limiting100 pulls/6h anonymously, CI/CD builds blockedProxy cache: 1 external pull → N internal pulls
AvailabilityDocker Hub outages = deployments stopImages cached locally
SecurityNo built-in vulnerability scanningTrivy scans every push automatically
ComplianceImages stored with a third party (USA)Data in your own datacentre
CostPaid plans for advanced featuresOpen source, full features

What Harbor manages

Harbor is no longer limited to Docker images. Since version 2.x, it also stores:

  • Container images: Docker, OCI, multi-architecture
  • Helm charts: versioned Kubernetes charts
  • SBOM (since v2.11): Software Bill of Materials for traceability
  • AI/ML artifacts (since v2.13): models through CloudNativeAI

Harbor architecture

Harbor is made of several services that talk to each other. Understanding this architecture helps you diagnose an outage and size the installation correctly: every component has its own bottleneck.

NGINX, a reverse proxy on port 443, serves the web portal and Harbor Core; Core relies on the Registry for storage, Trivy for scanning, JobService for tasks, PostgreSQL and Redis.NGINXreverse proxy, port 443Harbor Portalweb interfaceHarbor CoreAPI + logicRegistrystorageTrivyscannerJobServicejobsPostgreSQLdatabaseRediscache
Source · SVG
Esc to close, + and − to zoom, scroll to move around. 100 %

Main components:

ComponentRoleWhy it matters
NGINXReverse proxy, TLS terminationSingle entry point, HTTPS handling
CoreREST API, authentication, authorisationThe brain of Harbor
RegistryImage storage (Docker Distribution)Where your images are actually stored
TrivyVulnerability scanningDetects CVEs in your images
JobServiceAsynchronous tasks (replication, scan, GC)Background jobs
PostgreSQLDatabaseMetadata, users, projects
RedisCache and sessionsPerformance and user sessions

Built-in security features

Harbor integrates Trivy as its default vulnerability scanner. Every pushed image can be automatically scanned to detect known CVEs.

Scan workflow:

  1. A developer pushes an image
  2. Harbor automatically triggers Trivy
  3. Trivy analyses each layer of the image
  4. The results are attached to the image in the interface
  5. If critical vulnerabilities are detected, the pull can be blocked

Access control and authentication

Harbor offers several authentication methods to fit your infrastructure:

  • Local database: for small teams or labs
  • LDAP/Active Directory: integration with the corporate directory
  • OIDC (OpenID Connect): SSO with Keycloak, Azure AD, Okta, Google
  • Robot accounts: technical accounts for CI/CD pipelines (see the dedicated section)

When to choose Harbor rather than Pulp, Nexus or Artifactory?

Choose Harbor when you only store container images and Helm charts, and you want a registry that scans, controls access per project and replicates without assembling anything. As soon as a single RPM, npm or Maven package also has to be hosted, Harbor is no longer enough. The choice and licence table on the course home page puts the four tools side by side; this section spells out what sets Harbor apart from the other three.

The following diagram is the same as the one in the Artifactory guide: read the first question, which on its own points to Harbor, then follow the "no" exits to see where you end up when the need goes beyond images.

Decision tree: only container images and Helm charts leads to Harbor; otherwise, a requirement for 100% free software leads to Pulp; otherwise, the need for Xray, high availability or multi-site replication leads to Artifactory, and its absence to Nexus Community Edition.Do you store only containerimages and Helm charts?Harborspecialised image registryyesIs fully open source softwarerequired (no EULA, no quota)?noPulpmulti-format, GPLyesDo you need Xray, high availabilityor multi-site replication?noArtifactoryuniversal, commercialyesNexus Community Edition40,000 components, EULAno
Source · SVG
Esc to close, + and − to zoom, scroll to move around. 100 %

The criteria that set them apart

Four criteria can be checked without debate. The Pulp and Nexus columns point to their guides, Pulp as a container registry and Nexus as a Docker registry, so that you compare at equal scope: images.

CriterionHarborPulpNexus
LicenceApache-2.0, CNCF graduated projectGPL-2.0, no EULACommunity Edition under EULA
FormatsOCI images, Helm charts, SBOM, AI artifactsRPM, DEB, Python, npm, containersMaven, npm, PyPI, Docker and many others
Free version limitsNone: a single free editionNone40,000 components, 100,000 requests per day
Vulnerability scanningBuilt-in Trivy, pull blocking possibleTrivy plugged into the CINot covered in the course

One figure stands out from this table: the quota of 40,000 components in Nexus Community is worth watching for a very active image registry, since the CI pushes a new image on every commit. Harbor has no such ceiling, and the Nexus guide explains how to stay under the thresholds with cleanup policies.

What Harbor does that the others do not

Three functions justify it for images. The Trivy scan runs on every push and can block the pull of an image carrying critical CVEs, with no pipeline to write. Projects give each team its own rights, scan settings and revocable robot accounts. Finally replication, push and pull, as well as the proxy cache, synchronise images between registries without scripting.

Pulp also covers containers, but the scan is plugged in through the CI: the control has to be built, whereas it ships with Harbor.

What Harbor does not do

Harbor does not manage system packages (RPM, DEB) or libraries (Maven, npm, PyPI): it is an OCI artifact registry, not a universal repository. A team that also needs to cache PyPI or npm therefore adds a second tool, Pulp or Nexus, next to Harbor. Its installation is also heavier than a plain registry: seven services, including PostgreSQL and Redis, as the architecture diagram above shows.

The use case that justifies it

A Kubernetes platform where several teams push images, where you want to forbid the deployment of vulnerable images and protect yourself from Docker Hub rate limiting, justifies Harbor. Conversely, a team that only publishes Python or RPM packages has no use for it. As for Artifactory, it covers images like everything else, but under a commercial licence: as long as only images matter, Harbor avoids that cost.

Installing Harbor

Harbor can be installed in two ways depending on your environment:

MethodUse caseComplexity
Docker ComposeLab, small team, dedicated serverSimple
Helm on KubernetesProduction, high availability, cloudMedium

In this guide, we cover both methods. Start with Docker Compose to get familiar with Harbor, then move to Helm for production.

System requirements

Required hardware and software configuration:

ResourceMinimum (lab)Recommended (prod)Why
CPU2 cores4 coresTrivy uses a lot during scans
RAM4 GB8 GBPostgreSQL + Trivy + Redis
Disk40 GB160 GB+Depends on the volume of stored images

Required software:

  • Docker Engine (in French) 20.10.10+
  • Docker Compose v2 (or v1.18+)
  • OpenSSL (to generate the certificates)

Network ports to open:

PortProtocolUsage
443HTTPSHarbor portal and API (default)
80HTTPRedirect to HTTPS
4443HTTPSDocker Content Trust (optional)

Downloading Harbor

Download the installer from the official GitHub repository. Two options:

InstallerSizeUse case
Online~50 MBDownloads the images from Docker Hub at installation time
Offline~800 MBImages included, for environments without internet
  1. Download the archive

    Terminal window
    cd /opt
    wget https://github.com/goharbor/harbor/releases/download/v2.15.2/harbor-offline-installer-v2.15.2.tgz
  2. Verify authenticity

    Since late 2025, Harbor no longer signs its archives with GPG (the .asc file is gone) but with Sigstore/cosign: a .sigstore.json bundle accompanies each archive, plus an md5sum file. Check integrity first, then authenticity with cosign:

    Terminal window
    # Integrity (md5)
    wget https://github.com/goharbor/harbor/releases/download/v2.15.2/md5sum
    grep offline md5sum | md5sum -c -
    # Authenticity (Sigstore/cosign)
    wget https://github.com/goharbor/harbor/releases/download/v2.15.2/harbor-offline-installer-v2.15.2.tgz.sigstore.json
    cosign verify-blob \
    --bundle harbor-offline-installer-v2.15.2.tgz.sigstore.json \
    --certificate-identity-regexp 'https://github.com/goharbor/harbor' \
    --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
    harbor-offline-installer-v2.15.2.tgz
    # Verified OK
  3. Extract the archive

    Terminal window
    tar xzvf harbor-offline-installer-v2.15.2.tgz
    cd harbor

Configuring Harbor

The harbor.yml file holds the whole Harbor configuration. Copy the template and edit it:

Terminal window
cp harbor.yml.tmpl harbor.yml
vi harbor.yml

Here are the essential settings to configure:

# Hostname or public IP (never localhost in production)
hostname: registry.example.com
# HTTPS configuration (mandatory in production)
https:
port: 443
certificate: /opt/harbor/certs/server.crt
private_key: /opt/harbor/certs/server.key
# Initial admin password (change it!)
harbor_admin_password: YourSecurePassword
# Image storage directory
data_volume: /data
# Enable Trivy for vulnerability scanning
trivy:
ignore_unfixed: false # Include CVEs without a fix
security_check: vuln,config,secret
skip_update: false # Update the CVE database

Running the installation

The --with-trivy option enables vulnerability scanning:

Terminal window
sudo ./install.sh --with-trivy

The script checks the prerequisites, generates the configurations and starts the containers. Once it has finished:

✔ ----Harbor has been installed and started successfully.----

You can reach the Harbor web interface at https://registry.example.com (or the URL configured in hostname).

Installing with Helm (Kubernetes)

For a production deployment on Kubernetes, use the official Helm chart. This method brings high availability and better integration with the cloud-native ecosystem than installing from the archive.

  1. Add the Harbor Helm repository

    Terminal window
    helm repo add harbor https://helm.goharbor.io
    helm repo update
  2. Create a custom values file

    values-harbor.yaml
    expose:
    type: ingress
    ingress:
    hosts:
    core: harbor.example.com
    tls:
    enabled: true
    certSource: secret
    secret:
    secretName: harbor-tls
    externalURL: https://harbor.example.com
    persistence:
    enabled: true
    persistentVolumeClaim:
    registry:
    size: 100Gi
    trivy:
    enabled: true
    harborAdminPassword: "YourSecurePassword"
  3. Install Harbor

    Terminal window
    helm install harbor harbor/harbor \
    --namespace harbor \
    --create-namespace \
    -f values-harbor.yaml
  4. Check the deployment

    Terminal window
    kubectl -n harbor get pods

See the Harbor Helm documentation for advanced options (multi-replica HA, S3 storage, external PostgreSQL...).

First access

On your first access to Harbor:

  1. Open https://harbor.example.com in your browser
  2. Log in with admin and the password set in harbor.yml
  3. Change the password immediately via Administration → Users

Harbor web interface

Using Harbor day to day

This section covers the everyday operations: pushing an image, pulling it, and understanding vulnerability scanning.

Pushing your first image

Let's take a concrete example: you have a simple web application to containerise.

  1. Create a project in Harbor

    Before pushing an image, create a project in the Harbor interface: Projects → New Project. A project groups related images, by application or by team, and carries its own rights and scan settings.

  2. Create your Dockerfile

    FROM nginx:1.31.3-alpine@sha256:4a73073bd557c65b759505da037898b61f1be6cbcc3c2c3aeac22d2a470c1752
    COPY index.html /usr/share/nginx/html/
    EXPOSE 80
  3. Build the image

    Terminal window
    docker build -t mywebserver:0.1 .
  4. Tag the image for Harbor

    The tag format is: <harbor-url>/<project>/<image>:<version>

    Terminal window
    docker tag mywebserver:0.1 registry.example.com/myproject/mywebserver:0.1
  5. Log in to Harbor

    Terminal window
    docker login registry.example.com
    # Enter your Harbor credentials
  6. Push the image

    Terminal window
    docker push registry.example.com/myproject/mywebserver:0.1

Check: in the Harbor interface, go to Projects → myproject. You should see your image with its 0.1 tag.

Understanding vulnerability scanning

Once the image is pushed, Harbor automatically triggers a Trivy scan (if configured). In the interface:

  1. Click the image to see its tags
  2. Click a tag to see the detail
  3. The Vulnerabilities tab shows the detected CVEs

Harbor trivy

Interpreting the results:

SeverityMeaningRecommended action
CriticalRemotely exploitable flaw, major impactFix immediately
HighSerious flawFix quickly
MediumModerate flawPlan the fix
LowMinor flawFix when possible

Configuring the proxy cache

The proxy cache is one of Harbor's most useful features. It keeps a cache of the images of external registries, Docker Hub, Quay or GCR, in order to:

  • Avoid Docker Hub rate limiting (100 pulls/6h anonymously)
  • Speed up pulls (images served from your local network)
  • Guarantee availability even if Docker Hub is down

How does the proxy cache work?

The developer or Kubernetes runs a docker pull against Harbor in proxy-cache mode, which fetches the image from Docker Hub and then stores it in its local cache.docker pullfetch imagestoreDeveloperor K8sHarborproxy-cacheDocker HubupstreamLocal cacheimages
Source · SVG
Esc to close, + and − to zoom, scroll to move around. 100 %

First pull: Harbor fetches the image from Docker Hub, stores it locally, and serves it to the client.

Subsequent pulls: Harbor serves the image from its local cache. Docker Hub is not contacted (except to check for updates).

Configuring a Docker Hub proxy cache

  1. Create a registry endpoint

    In the Harbor interface: Administration → Registries → New Endpoint

    FieldValue
    ProviderDocker Hub
    Namedockerhub
    Endpoint URLhttps://hub.docker.com
    Access ID(optional, your Docker Hub username)
    Access Secret(optional, your Docker Hub token)

    Click Test Connection to check, then OK.

  2. Create a proxy cache project

    Projects → New Project

    FieldValue
    Project Namedockerhub-proxy
    Access LevelPublic (or Private depending on your needs)
    Proxy CacheEnabled
    Registrydockerhub (the endpoint created in step 1)
  3. Use the proxy cache

    Instead of:

    Terminal window
    # ❌ direct egress to Docker Hub, and a floating tag
    docker pull nginx:latest

    Use:

    Terminal window
    docker pull registry.example.com/dockerhub-proxy/library/nginx:1.31.3

    For non-official images, the publisher's path follows the same principle:

    Terminal window
    docker pull registry.example.com/dockerhub-proxy/library/alpine:3.22@sha256:5291449c3df73caf6ed85e649dec1b9e818b39a5d8c871e97afc13e9cd5e8fa8

Supported registries

Harbor supports the proxy cache for many registries:

  • Docker Hub
  • Quay.io
  • GitHub Container Registry (ghcr.io)
  • AWS ECR
  • Azure ACR
  • Google Container Registry
  • JFrog Artifactory

Robot accounts for CI/CD

Robot accounts are technical accounts designed for CI/CD pipelines. Unlike user accounts, they:

  • Have no access to the web interface
  • Have limited permissions (push/pull only)
  • Can be revoked without affecting users
  • Have a configurable lifetime

Creating a robot account

  1. Navigate to the project

    Projects → your-project → Robot Accounts

  2. Create the robot

    Click New Robot Account:

    FieldRecommended value
    Nameci-pipeline
    Expiration365 days (or according to your policy)
    PermissionsPush Artifact, Pull Artifact
  3. Save the credentials

    Harbor displays the token only once. Copy it immediately and store it in your secrets manager (Vault, GitLab CI variables, GitHub Secrets...).

Using it in GitLab CI

.gitlab-ci.yml
variables:
HARBOR_URL: registry.example.com
HARBOR_PROJECT: myproject
build:
stage: build
script:
- docker login -u "${HARBOR_ROBOT_USER}" -p "${HARBOR_ROBOT_TOKEN}" ${HARBOR_URL}
- docker build -t ${HARBOR_URL}/${HARBOR_PROJECT}/myapp:${CI_COMMIT_SHA} .
- docker push ${HARBOR_URL}/${HARBOR_PROJECT}/myapp:${CI_COMMIT_SHA}

The HARBOR_ROBOT_USER and HARBOR_ROBOT_TOKEN variables are defined in Settings → CI/CD → Variables (type "masked").

Replication between registries

Replication lets you synchronise images between several Harbor instances or towards other registries. Use cases:

  • Multi-datacentre: replicate images to a DR site
  • Edge computing: pre-push images to edge clusters
  • Migration: copy images from an old registry

Replication modes

ModeDirectionUse case
PushHarbor → ExternalDistribute to other registries
PullExternal → HarborImport from Docker Hub, GCR, etc.

Configuring push replication

  1. Create the destination endpoint

    Administration → Registries → New Endpoint

    Configure access to the destination registry (remote Harbor, ECR, etc.).

  2. Create a replication rule

    Administration → Replications → New Replication Rule

    FieldValue
    Nameprod-datacenter-2
    Replication modePush-based
    Source resource filtermyproject/**
    Destination registry(the endpoint you created)
    Trigger modeEvent Based (on every push)
  3. Test the replication

    Push an image to the source project. It should appear in the destination registry after a few seconds.

Troubleshooting

Problems with Harbor show up in two ways: the interface is unreachable, or Docker operations fail at login, push or pull. The most frequent causes are the following.

Installation problems

SymptomLikely causeSolution
Harbor does not startA container is in errordocker compose ps then the logs of the failing container
"port already in use" errorPort 443/80 already usedStop the conflicting service or change the port
Interface unreachableHTTPS misconfiguredCheck the certificate paths in harbor.yml
Database errorCorrupted PostgreSQLCheck the PostgreSQL logs in /var/log/harbor/

Docker connection problems

SymptomLikely causeSolution
x509: certificate signed by unknown authoritySelf-signed certificate not trustedAdd the CA to the system (see below)
unauthorized: authentication requiredWrong credentialsCheck username/password, run docker login again
denied: requested access to the resource is deniedInsufficient permissionsCheck the rights on the Harbor project
Timeout when pushingNetwork or firewallCheck connectivity on port 443

Trusting a self-signed certificate

If you use a self-signed certificate (lab), you must add it to the system:

Terminal window
# Copy the CA certificate
sudo cp ca.crt /usr/local/share/ca-certificates/harbor-ca.crt
sudo update-ca-certificates
# Restart Docker
sudo systemctl restart docker

Reading the logs

Harbor logs are stored in /var/log/harbor/ with one file per component:

Terminal window
# Core component logs (API)
tail -f /var/log/harbor/core.log
# Registry logs
tail -f /var/log/harbor/registry.log
# Trivy (scanner) logs
tail -f /var/log/harbor/trivy-adapter.log

For Helm installations, use kubectl:

Terminal window
kubectl -n harbor logs deployment/harbor-core -f

Key takeaways

  • Harbor is a cloud-native artifact registry that stores Docker images, Helm charts, SBOMs and AI artifacts
  • The proxy cache solves Docker Hub rate limiting: 1 external pull → N internal pulls
  • Trivy automatically scans images to detect CVEs
  • Robot accounts are essential for CI/CD: dedicated, revocable credentials with minimal permissions
  • Replication enables multi-datacentre setups and high availability
  • HTTPS is mandatory in production; Docker refuses HTTP registries by default
  • A CNCF graduated project = guaranteed maturity and longevity
  • You choose Harbor when only images and Helm charts matter; as soon as you also need RPM, npm or Maven, you add Pulp or Nexus, or take a universal repository

Knowledge check

Eight questions on Harbor: what an OCI-only registry buys you, its proxy cache, and the criteria that set it apart from Pulp and Nexus.

Knowledge check

Check what you have learned with this interactive quiz

8 questions
8 min
70% to pass

How it works

  • The timer starts when you click Start
  • Multiple choice, true/false and short answer questions
  • You can move between questions
  • Detailed results are shown at the end

Starts the quiz and the timer

Is this project useful to you?

The guides, courses, quizzes and labs stay free. If you use them regularly, you can contribute to their upkeep and development.

Become a supporting member (new tab) One-time support (new tab) Learn more

Follow the project on LinkedIn