Skip to content

Harbor Container Registry Setup: Kubernetes & Docker Compose with Network Storage

Objective: Master Harbor container registry deployment with production-grade storage and security. When you need enterprise container registry capabilities, when you want vulnerability scanning and image signing, when you're building secure CI/CD pipelines—Harbor becomes your weapon of choice.

Harbor is an open-source container registry that provides enterprise-grade features including vulnerability scanning, image signing, RBAC, and replication. This tutorial shows you how to deploy Harbor with the precision of a DevOps engineer, covering both Kubernetes and Docker Compose environments with network-attached storage.

0) Prerequisites (Read Once, Live by Them)

The Five Commandments

  1. Understand Harbor architecture
  2. Core components and microservices
  3. Database and Redis requirements
  4. Storage backend options and performance
  5. Security and authentication patterns

  6. Master storage configurations

  7. Network-attached storage (NFS, CIFS, iSCSI)
  8. Storage performance and capacity planning
  9. Backup and disaster recovery
  10. Storage security and access controls

  11. Know your deployment options

  12. Kubernetes vs Docker Compose trade-offs
  13. Resource requirements and scaling
  14. Network configuration and load balancing
  15. SSL/TLS and certificate management

  16. Validate everything

  17. Test storage connectivity and performance
  18. Verify Harbor functionality and security
  19. Monitor resource usage and health
  20. Test backup and recovery procedures

  21. Plan for production

  22. Security hardening and RBAC
  23. Monitoring and alerting
  24. Backup and disaster recovery
  25. Scaling and maintenance procedures

Why These Principles: Harbor deployment requires understanding both container orchestration and storage systems. Understanding these patterns prevents data loss and enables reliable registry operations.

1) Harbor Architecture Overview

Core Components

graph TB
    subgraph "Harbor Core Services"
        A[Proxy (Nginx)]
        B[Core API]
        C[Portal UI]
        D[Registry]
    end

    subgraph "Supporting Services"
        E[Database (PostgreSQL)]
        F[Redis Cache]
        G[Job Service]
        H[Chart Museum]
    end

    subgraph "Security Services"
        I[Notary (Signing)]
        J[Clair (Scanning)]
        K[Trivy (Scanning)]
    end

    subgraph "Storage Backend"
        L[Network Storage]
        M[Local Storage]
        N[Object Storage]
    end

    A --> B
    A --> C
    A --> D
    B --> E
    B --> F
    B --> G
    B --> H
    B --> I
    B --> J
    B --> K
    D --> L
    D --> M
    D --> N

    classDef core fill:#e1f5fe,stroke:#01579b,stroke-width:2px
    classDef support fill:#f3e5f5,stroke:#4a148c,stroke-width:2px
    classDef security fill:#e8f5e8,stroke:#1b5e20,stroke-width:2px
    classDef storage fill:#fff3e0,stroke:#e65100,stroke-width:2px

    class A,B,C,D core
    class E,F,G,H support
    class I,J,K security
    class L,M,N storage

Storage Architecture

graph LR
    subgraph "Harbor Registry"
        A[Registry Service]
        B[Storage Driver]
    end

    subgraph "Network Storage"
        C[NFS Server]
        D[CIFS Server]
        E[iSCSI Target]
    end

    subgraph "Storage Protocols"
        F[NFS v3/v4]
        G[CIFS/SMB]
        H[iSCSI]
    end

    A --> B
    B --> C
    B --> D
    B --> E
    C --> F
    D --> G
    E --> H

Why This Architecture Matters: Understanding Harbor's component relationships enables proper configuration and troubleshooting. This diagram shows the relationship between services and storage backends.

2) Prerequisites

Hardware Requirements

# Minimum hardware specification
hardware_requirements:
  kubernetes_deployment:
    master_nodes:
      - "4 CPU cores"
      - "8GB RAM"
      - "100GB storage"
    worker_nodes:
      - "4 CPU cores"
      - "8GB RAM"
      - "200GB storage"

  docker_compose_deployment:
    single_node:
      - "8 CPU cores"
      - "16GB RAM"
      - "500GB storage"

  network_storage:
    nfs_server:
      - "4 CPU cores"
      - "8GB RAM"
      - "2TB+ storage"
    performance:
      - "10Gbps network"
      - "SSD storage recommended"

Software Requirements

# Kubernetes requirements
kubectl version --client
kubectl cluster-info

# Docker Compose requirements
docker --version
docker-compose --version

# Network storage requirements
# NFS server
sudo apt install nfs-kernel-server nfs-common

# CIFS client
sudo apt install cifs-utils

# iSCSI client
sudo apt install open-iscsi

Network Storage Setup

# NFS Server Setup
sudo mkdir -p /srv/harbor-storage
sudo chown nobody:nogroup /srv/harbor-storage
sudo chmod 755 /srv/harbor-storage

# Configure NFS exports
echo "/srv/harbor-storage *(rw,sync,no_subtree_check,no_root_squash)" | sudo tee -a /etc/exports
sudo exportfs -ra
sudo systemctl enable nfs-kernel-server
sudo systemctl start nfs-kernel-server

# Test NFS connectivity
showmount -e <nfs-server-ip>

Why These Prerequisites Matter: Proper hardware and network setup prevents deployment failures. Understanding these requirements enables reliable Harbor operations.

3) Kubernetes Deployment

Harbor Helm Chart Setup

# Add Harbor Helm repository
helm repo add harbor https://helm.goharbor.io
helm repo update

# Create namespace
kubectl create namespace harbor

# Create values file
cat > harbor-values.yaml << EOF
expose:
  type: ingress
  tls:
    enabled: true
    secretName: harbor-tls
  ingress:
    hosts:
      core: harbor.example.com
      notary: notary.example.com

persistence:
  enabled: true
  resourcePolicy: "keep"
  persistentVolumeClaim:
    registry:
      storageClass: "nfs-storage"
      accessMode: ReadWriteMany
      size: 100Gi
    database:
      storageClass: "nfs-storage"
      accessMode: ReadWriteOnce
      size: 10Gi
    redis:
      storageClass: "nfs-storage"
      accessMode: ReadWriteOnce
      size: 1Gi

externalURL: https://harbor.example.com

chartmuseum:
  enabled: true
  persistence:
    enabled: true
    storageClass: "nfs-storage"
    size: 10Gi

trivy:
  enabled: true
  persistence:
    enabled: true
    storageClass: "nfs-storage"
    size: 10Gi

notary:
  enabled: true
  server:
    persistence:
      enabled: true
      storageClass: "nfs-storage"
      size: 1Gi
  signer:
    persistence:
      enabled: true
      storageClass: "nfs-storage"
      size: 1Gi
EOF

Storage Class Configuration

# nfs-storage-class.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-storage
provisioner: nfs.csi.k8s.io
parameters:
  server: <nfs-server-ip>
  share: /srv/harbor-storage
  mountPermissions: "0755"
reclaimPolicy: Retain
allowVolumeExpansion: true
volumeBindingMode: Immediate

Network Policies

# harbor-network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: harbor-network-policy
  namespace: harbor
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: ingress-nginx
    ports:
    - protocol: TCP
      port: 80
    - protocol: TCP
      port: 443
  egress:
  - to: []
    ports:
    - protocol: TCP
      port: 53
    - protocol: UDP
      port: 53

Harbor Deployment

# Deploy Harbor with Helm
helm install harbor harbor/harbor \
  --namespace harbor \
  --values harbor-values.yaml \
  --wait

# Verify deployment
kubectl get pods -n harbor
kubectl get pvc -n harbor

# Check Harbor status
kubectl get ingress -n harbor

Why Kubernetes Deployment Matters: Kubernetes provides high availability, scalability, and resource management. Understanding these patterns enables production-ready Harbor deployments.

4) Docker Compose Deployment

Harbor Installation

# Download Harbor offline installer
wget https://github.com/goharbor/harbor/releases/download/v2.8.0/harbor-offline-installer-v2.8.0.tgz
tar xzf harbor-offline-installer-v2.8.0.tgz
cd harbor

Docker Compose Configuration

# docker-compose.yml
version: '3.8'

services:
  proxy:
    image: goharbor/nginx-photon:v2.8.0
    container_name: nginx
    restart: always
    volumes:
      - ./common/config/nginx:/etc/nginx:z
    networks:
      - harbor
    ports:
      - 80:8080
      - 443:8443

  registry:
    image: goharbor/harbor-registryctl:v2.8.0
    container_name: registry
    restart: always
    volumes:
      - /data/registry:/storage:z
      - ./common/config/registry/:/etc/registry:z
    networks:
      - harbor
    depends_on:
      - log

  core:
    image: goharbor/harbor-core:v2.8.0
    container_name: harbor-core
    restart: always
    volumes:
      - /data/ca_download/:/etc/core/ca/:z
      - /data/:/data/:z
      - ./common/config/core/app.conf:/etc/core/app.conf:z
      - ./common/config/core/private_key.pem:/etc/core/private_key.pem:z
    networks:
      - harbor
    depends_on:
      - log
      - registry
      - redis
      - database

  portal:
    image: goharbor/harbor-portal:v2.8.0
    container_name: harbor-portal
    restart: always
    volumes:
      - ./common/config/portal/:/etc/portal:z
    networks:
      - harbor
    depends_on:
      - log

  log:
    image: goharbor/harbor-log:v2.8.0
    container_name: harbor-log
    restart: always
    volumes:
      - /var/log/docker/:/var/log/docker/:z
      - ./common/config/log/logrotate.conf:/etc/logrotate.d/logrotate.conf:z
      - ./common/config/log/rsyslog_docker.conf:/etc/rsyslog.d/00-rsyslog-docker.conf:z
    networks:
      - harbor
    ports:
      - 127.0.0.1:1514:10514

  database:
    image: goharbor/harbor-db:v2.8.0
    container_name: harbor-db
    restart: always
    volumes:
      - /data/database:/var/lib/postgresql/data:z
    networks:
      - harbor
    environment:
      POSTGRES_DB: registry
      POSTGRES_PASSWORD: root123
      POSTGRES_USER: postgres

  redis:
    image: goharbor/redis-photon:v2.8.0
    container_name: redis
    restart: always
    volumes:
      - /data/redis:/var/lib/redis:z
    networks:
      - harbor

  jobservice:
    image: goharbor/harbor-jobservice:v2.8.0
    container_name: harbor-jobservice
    restart: always
    volumes:
      - /data/job_logs:/var/log/jobs:z
      - ./common/config/jobservice:/etc/jobservice:z
    networks:
      - harbor
    depends_on:
      - log
      - redis
      - core

  trivy:
    image: goharbor/trivy-adapter-photon:v2.8.0
    container_name: trivy-adapter
    restart: always
    volumes:
      - /data/trivy-adapter/trivy:/var/lib/trivy:z
      - /data/trivy-adapter/cache:/root/.cache/trivy:z
    networks:
      - harbor
    depends_on:
      - log
      - redis

  chartmuseum:
    image: goharbor/chartmuseum-photon:v2.8.0
    container_name: chartmuseum
    restart: always
    volumes:
      - /data/chart_storage:/chart_storage:z
    networks:
      - harbor
    depends_on:
      - log

  notary-server:
    image: goharbor/notary-server-photon:v2.8.0
    container_name: notary-server
    restart: always
    volumes:
      - /data/notary-server:/var/notary:z
      - ./common/config/notary/notary-server.crt:/etc/ssl/notary/notary-server.crt:z
      - ./common/config/notary/notary-server.key:/etc/ssl/notary/notary-server.key:z
    networks:
      - harbor
    depends_on:
      - log

  notary-signer:
    image: goharbor/notary-signer-photon:v2.8.0
    container_name: notary-signer
    restart: always
    volumes:
      - /data/notary-signer:/var/notary:z
      - ./common/config/notary/notary-signer.crt:/etc/ssl/notary/notary-signer.crt:z
      - ./common/config/notary/notary-signer.key:/etc/ssl/notary/notary-signer.key:z
    networks:
      - harbor
    depends_on:
      - log

networks:
  harbor:
    external: false

Harbor Configuration

# harbor.yml
# Configuration file of Harbor

# The IP address or hostname to access admin UI and registry service.
# DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients.
hostname: harbor.example.com

# http related config
http:
  # port for http, default is 80. If https enabled, this port will redirect to https port.
  port: 80

# 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

# # Uncomment following will enable tls communication between all harbor components
# internal_tls:
#   # set enabled to true means internal tls is enabled
#   enabled: true
#   # put your cert and key files on dir
#   dir: /etc/harbor/tls/internal

# Uncomment external_url if you want to enable external proxy
# And when it enabled the hostname will no longer used
# external_url: https://reg.mydomain.com:8433

# The initial password of Harbor admin
# It only works in first time to install Harbor
# Remember Change the admin password from UI after launching Harbor.
harbor_admin_password: Harbor12345

# Harbor DB configuration
database:
  # The password for the root user of Harbor DB. Change this before any production use.
  password: root123
  # The maximum number of connections in the idle connection pool. If it <=0, no idle connections are retained.
  max_idle_conns: 50
  # The maximum number of open connections to the database. If it <= 0, then there is no limit on the number of open connections.
  # Note: the default number of connections is 100 for postgres of harbor.
  max_open_conns: 1000
  # The maximum amount of time a connection may be reused. Expired connections may be closed lazily before reuse. If it <= 0, connections are not closed due to a connection's age.
  conn_max_lifetime: 5m
  # The maximum amount of time a connection may be idle. Expired connections may be closed lazily before reuse. If it <= 0, connections are not closed due to a connection's idle time.
  conn_max_idle_time: 0

# The default data volume
data_volume: /data

# Harbor Storage settings by default is using /data dir on local filesystem
# Uncomment storage_service setting If you want to using external storage
storage_service:
  # ca_bundle is the path to the custom root ca certificate, which will be injected into the truststore
  # of registry's and chart repository's containers.  This is usually needed when the user hosts a internal storage with self signed certificate.
  ca_bundle:

  # storage backend, default is filesystem, options include filesystem, azure, gcs, s3, swift and oss
  # for more info about this configuration please refer https://docs.docker.com/registry/configuration/
  filesystem:
    rootdirectory: /storage
  # s3:
  #   accesskey: awsaccesskey
  #   secretkey: awssecretkey
  #   region: us-west-1
  #   regionendpoint: http://myobjects.local
  #   bucket: bucketname
  #   encrypt: true
  #   keyid: mykeyid
  #   secure: true
  #   v4auth: true
  #   chunksize: 5242880
  #   rootdirectory: /s3/object/name/prefix
  # azure:
  #   accountname: accountname
  #   accountkey: base64encodedaccountkey
  #   container: containername
  #   realm: core.windows.net
  # gcs:
  #   bucket: bucketname
  #   keyfile: /path/to/keyfile
  #   rootdirectory: /gcs/object/name/prefix
  # oss:
  #   accesskeyid: accesskeyid
  #   accesskeysecret: accesskeysecret
  #   region: regionname
  #   endpoint: endpoint
  #   bucket: bucketname
  #   encrypt: true
  #   secure: true
  #   chunksize: 10485760
  #   rootdirectory: /oss/object/name/prefix
  # swift:
  #   username: username
  #   password: password
  #   authurl: https://storage.myprovider.com/v3/auth
  #   tenant: tenantname
  #   tenantid: tenantid
  #   domain: domainname
  #   domainid: domainid
  #   region: fr
  #   container: containername
  #   rootdirectory: /swift/object/name/prefix

# Trivy configuration
trivy:
  # ignoreUnfixed The flag to display only fixed vulnerabilities
  ignore_unfixed: false
  # skipUpdate The flag to enable/disable Trivy DB downloads from GitHub
  skip_update: false
  # offlineScan The flag to enable/disable Trivy offline mode
  offline_scan: false
  # securityCheck The types of security checks to perform
  security_check: vuln
  # insecure The flag to skip verifying registry certificate
  insecure: false
  # github_token The GitHub access token to download Trivy DB
  # github_token: xxx

jobservice:
  # Maximum number of job workers in job service
  max_job_workers: 10

notification:
  # Maximum retry count that webhook job will retry
  webhook_job_max_retry: 10

chart:
  # Change the value of absolute_url to enabled can enable absolute url in chart
  absolute_url: disabled

# Log configurations
log:
  # options are debug, info, warning, error, fatal
  level: info
  # configs for files
  local:
    # Log rotate count, default is 50
    rotate_count: 50
    # Log rotate size, default is 200M
    rotate_size: 200M
    # Log directory, default is /var/log/harbor
    location: /var/log/harbor

#This attribute is for migrator to detect the version of the .cfg file, DO NOT MODIFY!
_version: 2.8.0

# Uncomment external_database if using external database.
# external_database:
#   harbor:
#     host: harbor_db_host
#     port: harbor_db_port
#     db_name: harbor
#     username: harbor
#     password: password
#     ssl_mode: disable
#     max_idle_conns: 2
#     max_open_conns: 0
#   notary_signer:
#     host: notary_signer_db_host
#     port: notary_signer_db_port
#     db_name: notary_signer
#     username: notary_signer
#     password: password
#     ssl_mode: disable
#   notary_server:
#     host: notary_server_db_host
#     port: notary_server_db_port
#     db_name: notary_server
#     username: notary_server
#     password: password
#     ssl_mode: disable

# Uncomment external_redis if using external Redis server
# external_redis:
#   # support redis, redis+sentinel
#   # # host for redis: <host_redis>:<port_redis>
#   # # host for redis+sentinel:
#   # #  <host_sentinel1>:<port_sentinel1> <host_sentinel2>:<port_sentinel2> <host_sentinel3>:<port_sentinel3>
#   host: redis:6379
#   password: ""
#   # sentinel_master_set must be set to support redis+sentinel
#   #sentinel_master_set:
#   #db_index: 0

# Uncomment uaa for trusting the certificate of uaa instance that is hosted via self-signed cert.
# uaa:
#   ca_file: /path/to/ca

# Global proxy
# Config http proxy for components, e.g. http://my.proxy.com:3128
# Components doesn't need to connect to each others via http proxy.
# Remove component from `components` array if want disable proxy
# for specific component.
# Supported components: [registry, core, portal, jobservice, trivy, chartmuseum, notary, database, redis]
proxy:
  http_proxy:
  https_proxy:
  no_proxy:
  components:
    - core
    - jobservice
    - trivy

Network Storage Mount

# Mount NFS storage
sudo mkdir -p /data
sudo mount -t nfs <nfs-server-ip>:/srv/harbor-storage /data

# Make mount persistent
echo "<nfs-server-ip>:/srv/harbor-storage /data nfs defaults 0 0" | sudo tee -a /etc/fstab

# Set proper permissions
sudo chown -R 10000:10000 /data
sudo chmod -R 755 /data

Harbor Installation

# Install Harbor
sudo ./install.sh

# Verify installation
docker-compose ps

# Access Harbor
curl -k https://harbor.example.com

Why Docker Compose Deployment Matters: Docker Compose provides simple deployment and management. Understanding these patterns enables reliable single-node Harbor deployments.

5) Network Storage Configuration

NFS Server Setup

# Install NFS server
sudo apt update
sudo apt install nfs-kernel-server nfs-common

# Create storage directories
sudo mkdir -p /srv/harbor-storage/{registry,database,redis,chart,trivy,notary}
sudo chown -R 10000:10000 /srv/harbor-storage

# Configure NFS exports
cat > /etc/exports << EOF
/srv/harbor-storage *(rw,sync,no_subtree_check,no_root_squash)
EOF

# Start NFS services
sudo systemctl enable nfs-kernel-server
sudo systemctl start nfs-kernel-server
sudo exportfs -ra

CIFS/SMB Configuration

# Install CIFS utilities
sudo apt install cifs-utils

# Create mount point
sudo mkdir -p /data

# Mount CIFS share
sudo mount -t cifs //<smb-server>/harbor-storage /data \
  -o username=<username>,password=<password>,uid=10000,gid=10000,iocharset=utf8

# Make mount persistent
echo "//<smb-server>/harbor-storage /data cifs username=<username>,password=<password>,uid=10000,gid=10000,iocharset=utf8 0 0" | sudo tee -a /etc/fstab

iSCSI Configuration

# Install iSCSI initiator
sudo apt install open-iscsi

# Discover iSCSI targets
sudo iscsiadm -m discovery -t st -p <iscsi-server-ip>

# Login to iSCSI target
sudo iscsiadm -m node -T <target-name> -p <iscsi-server-ip> -l

# Create filesystem
sudo mkfs.ext4 /dev/sdb
sudo mkdir -p /data
sudo mount /dev/sdb /data

Storage Performance Tuning

# NFS performance tuning
echo "nfs.nfsd.nfs4_disable_idmapping=Y" | sudo tee -a /etc/modprobe.d/nfs.conf
echo "nfs.client.nfs4_disable_idmapping=Y" | sudo tee -a /etc/modprobe.d/nfs.conf

# CIFS performance tuning
echo "//<smb-server>/harbor-storage /data cifs username=<username>,password=<password>,uid=10000,gid=10000,iocharset=utf8,cache=strict,rsize=1048576,wsize=1048576 0 0" | sudo tee -a /etc/fstab

# iSCSI performance tuning
echo "node.session.iscsi.InitialR2T = No" | sudo tee -a /etc/iscsi/iscsid.conf
echo "node.session.iscsi.ImmediateData = Yes" | sudo tee -a /etc/iscsi/iscsid.conf

Why Network Storage Matters: Proper storage configuration enables reliable data persistence and performance. Understanding these patterns prevents data loss and enables scalable Harbor deployments.

6) Security Configuration

SSL/TLS Setup

# Generate self-signed certificate
openssl req -x509 -newkey rsa:4096 -keyout harbor.key -out harbor.crt -days 365 -nodes \
  -subj "/C=US/ST=State/L=City/O=Organization/CN=harbor.example.com"

# Copy certificates
sudo cp harbor.crt /etc/ssl/certs/
sudo cp harbor.key /etc/ssl/private/
sudo chmod 600 /etc/ssl/private/harbor.key

Harbor Security Settings

# harbor-security.yml
# Security configuration for Harbor

# Enable vulnerability scanning
trivy:
  enabled: true
  ignore_unfixed: false
  skip_update: false
  offline_scan: false

# Enable image signing
notary:
  enabled: true

# RBAC configuration
rbac:
  enabled: true
  admin_users:
    - admin
  project_creators:
    - admin

# Security policies
security:
  # Require signed images
  require_signed_images: true

  # Vulnerability scanning policy
  vulnerability_scanning:
    enabled: true
    severity_threshold: "high"

  # Content trust
  content_trust:
    enabled: true

Network Security

# Configure firewall
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 22/tcp
sudo ufw enable

# Configure fail2ban
sudo apt install fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Why Security Configuration Matters: Proper security settings prevent unauthorized access and ensure data integrity. Understanding these patterns enables secure Harbor deployments.

7) Monitoring and Logging

Prometheus Monitoring

# harbor-monitoring.yml
# Prometheus configuration for Harbor monitoring

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'harbor'
    static_configs:
      - targets: ['harbor.example.com:80']
    metrics_path: '/api/v2.0/systeminfo'
    scheme: https
    tls_config:
      insecure_skip_verify: true

Grafana Dashboard

{
  "dashboard": {
    "title": "Harbor Registry Monitoring",
    "panels": [
      {
        "title": "Registry Health",
        "type": "stat",
        "targets": [
          {
            "expr": "harbor_registry_health",
            "legendFormat": "Registry Health"
          }
        ]
      },
      {
        "title": "Storage Usage",
        "type": "graph",
        "targets": [
          {
            "expr": "harbor_storage_usage_bytes",
            "legendFormat": "Storage Usage"
          }
        ]
      }
    ]
  }
}

Log Aggregation

# docker-compose.logging.yml
version: '3.8'

services:
  harbor-log:
    image: goharbor/harbor-log:v2.8.0
    container_name: harbor-log
    restart: always
    volumes:
      - /var/log/harbor:/var/log/harbor:z
    networks:
      - harbor
    ports:
      - "127.0.0.1:1514:10514"

  fluentd:
    image: fluent/fluentd:v1.16-debian-1
    container_name: fluentd
    restart: always
    volumes:
      - ./fluentd/conf:/fluentd/etc
      - /var/log/harbor:/var/log/harbor:ro
    networks:
      - harbor
    depends_on:
      - harbor-log

Why Monitoring Matters: Proper monitoring enables proactive management and troubleshooting. Understanding these patterns prevents service disruptions and enables reliable Harbor operations.

8) Backup and Disaster Recovery

Backup Script

#!/bin/bash
# harbor-backup.sh

set -e

BACKUP_DIR="/backup/harbor"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="harbor-backup-${DATE}.tar.gz"

# Create backup directory
mkdir -p $BACKUP_DIR

# Backup Harbor data
tar -czf "${BACKUP_DIR}/${BACKUP_FILE}" \
  /data/registry \
  /data/database \
  /data/redis \
  /data/chart \
  /data/trivy \
  /data/notary

# Backup Harbor configuration
tar -czf "${BACKUP_DIR}/harbor-config-${DATE}.tar.gz" \
  /etc/harbor \
  /opt/harbor

# Cleanup old backups (keep 30 days)
find $BACKUP_DIR -name "harbor-backup-*.tar.gz" -mtime +30 -delete
find $BACKUP_DIR -name "harbor-config-*.tar.gz" -mtime +30 -delete

echo "Backup completed: ${BACKUP_DIR}/${BACKUP_FILE}"

Restore Script

#!/bin/bash
# harbor-restore.sh

set -e

BACKUP_FILE=$1
RESTORE_DIR="/data"

if [ -z "$BACKUP_FILE" ]; then
    echo "Usage: $0 <backup-file>"
    exit 1
fi

# Stop Harbor services
docker-compose down

# Restore data
tar -xzf "$BACKUP_FILE" -C /

# Start Harbor services
docker-compose up -d

echo "Restore completed"

Disaster Recovery Plan

# disaster-recovery.yml
# Disaster recovery procedures for Harbor

procedures:
  data_loss:
    - "Stop Harbor services"
    - "Restore from latest backup"
    - "Verify data integrity"
    - "Start Harbor services"
    - "Test functionality"

  complete_failure:
    - "Provision new infrastructure"
    - "Install Harbor from scratch"
    - "Restore from backup"
    - "Update DNS records"
    - "Verify functionality"

  partial_failure:
    - "Identify failed components"
    - "Restore specific components"
    - "Verify component health"
    - "Test functionality"

Why Backup and Recovery Matters: Proper backup procedures prevent data loss and enable quick recovery. Understanding these patterns prevents service disruptions and enables reliable Harbor operations.

9) Scaling and Performance

Horizontal Scaling

# harbor-scale.yml
# Horizontal scaling configuration for Harbor

# Load balancer configuration
nginx:
  replicas: 3
  resources:
    requests:
      cpu: 100m
      memory: 128Mi
    limits:
      cpu: 500m
      memory: 512Mi

# Registry scaling
registry:
  replicas: 2
  resources:
    requests:
      cpu: 200m
      memory: 256Mi
    limits:
      cpu: 1000m
      memory: 1Gi

# Job service scaling
jobservice:
  replicas: 3
  resources:
    requests:
      cpu: 100m
      memory: 128Mi
    limits:
      cpu: 500m
      memory: 512Mi

Performance Tuning

# harbor-performance.yml
# Performance tuning configuration

# Database tuning
database:
  postgresql:
    shared_buffers: 256MB
    effective_cache_size: 1GB
    work_mem: 4MB
    maintenance_work_mem: 64MB

# Redis tuning
redis:
  maxmemory: 256mb
  maxmemory_policy: allkeys-lru

# Registry tuning
registry:
  storage:
    cache:
      blobdescriptor: inmemory
    maintenance:
      uploadpurging:
        enabled: true
        age: 168h
        interval: 24h
        dryrun: false

Caching Configuration

# harbor-caching.yml
# Caching configuration for Harbor

# Redis caching
redis:
  enabled: true
  host: redis
  port: 6379
  password: ""
  database: 0

# CDN configuration
cdn:
  enabled: true
  provider: nginx
  cache_control: "public, max-age=31536000"
  expires: "1y"

Why Scaling and Performance Matters: Proper scaling enables high availability and performance. Understanding these patterns prevents bottlenecks and enables scalable Harbor deployments.

10) Troubleshooting

Common Issues

# Check Harbor status
docker-compose ps
docker-compose logs

# Check storage connectivity
df -h
mount | grep nfs
mount | grep cifs

# Check network
netstat -tlnp
ss -tlnp

# Check Harbor health
curl -k https://harbor.example.com/api/v2.0/systeminfo

Log Analysis

# Harbor logs
docker-compose logs harbor-core
docker-compose logs harbor-registry
docker-compose logs harbor-portal

# System logs
journalctl -u docker
journalctl -u nfs-kernel-server

Performance Monitoring

# Resource usage
docker stats
htop
iostat -x 1

# Network monitoring
iftop
netstat -i

Why Troubleshooting Matters: Proper troubleshooting procedures enable quick issue resolution. Understanding these patterns prevents service disruptions and enables reliable Harbor operations.

11) TL;DR Quickstart

Essential Commands

# Kubernetes deployment
helm repo add harbor https://helm.goharbor.io
helm install harbor harbor/harbor --namespace harbor --values harbor-values.yaml

# Docker Compose deployment
wget https://github.com/goharbor/harbor/releases/download/v2.8.0/harbor-offline-installer-v2.8.0.tgz
tar xzf harbor-offline-installer-v2.8.0.tgz
cd harbor
sudo ./install.sh

# Storage setup
sudo mkdir -p /data
sudo mount -t nfs <nfs-server>:/srv/harbor-storage /data

# Verify deployment
curl -k https://harbor.example.com

Essential Patterns

# Essential Harbor patterns
harbor_patterns:
  kubernetes: "helm install harbor harbor/harbor"
  docker_compose: "sudo ./install.sh"
  storage: "mount -t nfs <server>:/path /data"
  backup: "tar -czf backup.tar.gz /data"
  restore: "tar -xzf backup.tar.gz -C /"
  monitoring: "curl -k https://harbor.example.com/api/v2.0/systeminfo"

Troubleshooting Checklist

# Troubleshooting checklist
troubleshooting:
  connectivity: "curl -k https://harbor.example.com"
  storage: "df -h && mount | grep nfs"
  services: "docker-compose ps"
  logs: "docker-compose logs"
  performance: "docker stats && htop"

Why This Quickstart: These patterns cover 90% of Harbor deployment and management. Master these before exploring advanced features.

12) The Machine's Summary

Harbor deployment requires understanding both container orchestration and storage systems. When used correctly, Harbor enables enterprise-grade container registry capabilities with vulnerability scanning, image signing, and RBAC. The key is understanding storage requirements, mastering security configuration, and following best practices.

The Dark Truth: Without proper Harbor understanding, your container registry is vulnerable and unreliable. Harbor is your weapon. Use it wisely.

The Machine's Mantra: "In security we trust, in Harbor we store, and in the registry we find the path to enterprise container management."

Why This Matters: Harbor enables secure container registry operations that can handle enterprise workloads, maintain data integrity, and provide reliable container storage while ensuring security and compliance.


This tutorial provides the complete machinery for deploying Harbor with network storage. The patterns scale from simple single-node deployments to complex enterprise clusters, from basic container storage to advanced security and compliance.