docker.recipes

Harbor Container Registry

advanced

Enterprise-class container registry with vulnerability scanning, image signing, and replication.

Overview

Harbor Container Registry is an open-source, enterprise-grade container registry that extends Docker Distribution with security-focused features including vulnerability scanning, content signing, and role-based access control. Originally created by VMware and now a CNCF graduated project, Harbor addresses the security and governance gaps in basic container registries by providing comprehensive image lifecycle management with built-in security scanning via Trivy, multi-tenancy support, and replication capabilities for distributed deployments. This Harbor deployment stack combines the Harbor core services with PostgreSQL for metadata storage, Redis for caching and session management, Trivy for vulnerability scanning, and NGINX as a reverse proxy. The architecture separates concerns across multiple specialized containers: harbor-core handles API operations and authentication, harbor-portal provides the web interface, jobservice manages background tasks like garbage collection and replication, while registryctl manages the underlying Docker registry storage. This multi-service approach enables horizontal scaling and independent updates of components. This configuration is ideal for organizations requiring private container registries with enterprise security features, development teams needing vulnerability scanning integrated into their CI/CD pipelines, and compliance-driven environments where image provenance and security scanning are mandatory. The stack provides a self-hosted alternative to managed registry services while offering more advanced security and governance features than basic Docker Registry deployments, making it particularly valuable for air-gapped environments, multi-tenant scenarios, and organizations with strict data sovereignty requirements.

Key Features

  • Trivy-powered vulnerability scanning with CVE database integration and severity-based policy enforcement
  • Content signing and trust verification using Docker Content Trust and Notary integration
  • Role-based access control with project-level permissions and LDAP/OIDC authentication support
  • Multi-registry replication for disaster recovery and geographically distributed deployments
  • Webhook notifications for image push/pull events and vulnerability scan results
  • Project quotas and resource management with storage usage tracking and limits
  • Comprehensive audit logging for compliance with detailed user activity tracking
  • Garbage collection automation for efficient storage management and cleanup policies

Common Use Cases

  • 1Enterprise container registry with security scanning for large development teams requiring vulnerability assessment
  • 2Air-gapped environments needing private registry with offline vulnerability database updates
  • 3Multi-tenant SaaS platforms requiring project isolation and granular access controls per customer
  • 4Compliance-driven organizations needing audit trails and image signing for regulatory requirements
  • 5Hybrid cloud deployments requiring image replication between on-premises and cloud registries
  • 6DevSecOps pipelines integrating vulnerability scanning gates before production deployments
  • 7Container supply chain security implementations requiring image provenance and trust verification

Prerequisites

  • Minimum 4GB RAM and 2 CPU cores for Harbor core services plus database and cache components
  • 50GB+ available storage for container images, vulnerability database, and PostgreSQL data
  • Ports 80 and 443 available for HTTP/HTTPS access through NGINX reverse proxy
  • SSL certificates configured for production HTTPS access and Docker client trust
  • Understanding of container registry concepts, Docker authentication, and certificate management
  • Network connectivity for Trivy vulnerability database updates and image replication if required

For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms

docker-compose.yml

docker-compose.yml
1services:
2 log:
3 image: goharbor/harbor-log:latest
4 volumes:
5 - harbor_log:/var/log/docker/:z
6 - ./config/log/logrotate.conf:/etc/logrotate.d/logrotate.conf:z
7 networks:
8 - harbor-net
9 restart: unless-stopped
10
11 registry:
12 image: goharbor/registry-photon:latest
13 volumes:
14 - registry_data:/storage:z
15 - ./config/registry/config.yml:/etc/registry/config.yml:z
16 networks:
17 - harbor-net
18 depends_on:
19 - log
20 restart: unless-stopped
21
22 registryctl:
23 image: goharbor/harbor-registryctl:latest
24 volumes:
25 - registry_data:/storage:z
26 - ./config/registry/config.yml:/etc/registry/config.yml:z
27 - ./config/registryctl/config.yml:/etc/registryctl/config.yml:z
28 networks:
29 - harbor-net
30 restart: unless-stopped
31
32 postgresql:
33 image: goharbor/harbor-db:latest
34 environment:
35 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
36 volumes:
37 - database:/var/lib/postgresql/data:z
38 networks:
39 - harbor-net
40 restart: unless-stopped
41
42 core:
43 image: goharbor/harbor-core:latest
44 environment:
45 CORE_KEY: ${CORE_KEY}
46 _REDIS_URL_CORE: redis://redis:6379/0
47 SYNC_REGISTRY: "false"
48 CHART_CACHE_DRIVER: redis
49 _REDIS_URL_REG: redis://redis:6379/1
50 PORTAL_URL: http://portal:8080
51 REGISTRY_URL: http://registry:5000
52 TOKEN_SERVICE_URL: http://core:8080/service/token
53 HARBOR_ADMIN_PASSWORD: ${HARBOR_ADMIN_PASSWORD}
54 DATABASE_TYPE: postgresql
55 volumes:
56 - core_data:/data:z
57 - ./config/core/app.conf:/etc/core/app.conf:z
58 networks:
59 - harbor-net
60 depends_on:
61 - log
62 - registry
63 - postgresql
64 - redis
65 restart: unless-stopped
66
67 portal:
68 image: goharbor/harbor-portal:latest
69 networks:
70 - harbor-net
71 depends_on:
72 - log
73 - core
74 restart: unless-stopped
75
76 jobservice:
77 image: goharbor/harbor-jobservice:latest
78 volumes:
79 - job_logs:/var/log/jobs:z
80 - ./config/jobservice/config.yml:/etc/jobservice/config.yml:z
81 networks:
82 - harbor-net
83 depends_on:
84 - core
85 restart: unless-stopped
86
87 redis:
88 image: goharbor/redis-photon:latest
89 volumes:
90 - redis_data:/var/lib/redis
91 networks:
92 - harbor-net
93 restart: unless-stopped
94
95 trivy-adapter:
96 image: goharbor/trivy-adapter-photon:latest
97 environment:
98 SCANNER_TRIVY_CACHE_DIR: /home/scanner/.cache/trivy
99 SCANNER_TRIVY_REPORTS_DIR: /home/scanner/.cache/reports
100 volumes:
101 - trivy_cache:/home/scanner/.cache
102 networks:
103 - harbor-net
104 restart: unless-stopped
105
106 proxy:
107 image: goharbor/nginx-photon:latest
108 ports:
109 - "80:8080"
110 - "443:8443"
111 volumes:
112 - ./config/nginx:/etc/nginx:z
113 networks:
114 - harbor-net
115 depends_on:
116 - registry
117 - core
118 - portal
119 restart: unless-stopped
120
121volumes:
122 harbor_log:
123 registry_data:
124 database:
125 core_data:
126 job_logs:
127 redis_data:
128 trivy_cache:
129
130networks:
131 harbor-net:
132 driver: bridge

.env Template

.env
1# Harbor Admin Password
2HARBOR_ADMIN_PASSWORD=Harbor12345
3
4# PostgreSQL
5POSTGRES_PASSWORD=secure_postgres_password
6
7# Core Secret Key
8CORE_KEY=your_32_char_secret_key_here

Usage Notes

  1. 1Harbor UI at https://localhost
  2. 2Default login: admin / Harbor12345
  3. 3Includes Trivy vulnerability scanning
  4. 4Use harbor installer for full setup

Individual Services(10 services)

Copy individual services to mix and match with your existing compose files.

log
log:
  image: goharbor/harbor-log:latest
  volumes:
    - harbor_log:/var/log/docker/:z
    - ./config/log/logrotate.conf:/etc/logrotate.d/logrotate.conf:z
  networks:
    - harbor-net
  restart: unless-stopped
registry
registry:
  image: goharbor/registry-photon:latest
  volumes:
    - registry_data:/storage:z
    - ./config/registry/config.yml:/etc/registry/config.yml:z
  networks:
    - harbor-net
  depends_on:
    - log
  restart: unless-stopped
registryctl
registryctl:
  image: goharbor/harbor-registryctl:latest
  volumes:
    - registry_data:/storage:z
    - ./config/registry/config.yml:/etc/registry/config.yml:z
    - ./config/registryctl/config.yml:/etc/registryctl/config.yml:z
  networks:
    - harbor-net
  restart: unless-stopped
postgresql
postgresql:
  image: goharbor/harbor-db:latest
  environment:
    POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
  volumes:
    - database:/var/lib/postgresql/data:z
  networks:
    - harbor-net
  restart: unless-stopped
core
core:
  image: goharbor/harbor-core:latest
  environment:
    CORE_KEY: ${CORE_KEY}
    _REDIS_URL_CORE: redis://redis:6379/0
    SYNC_REGISTRY: "false"
    CHART_CACHE_DRIVER: redis
    _REDIS_URL_REG: redis://redis:6379/1
    PORTAL_URL: http://portal:8080
    REGISTRY_URL: http://registry:5000
    TOKEN_SERVICE_URL: http://core:8080/service/token
    HARBOR_ADMIN_PASSWORD: ${HARBOR_ADMIN_PASSWORD}
    DATABASE_TYPE: postgresql
  volumes:
    - core_data:/data:z
    - ./config/core/app.conf:/etc/core/app.conf:z
  networks:
    - harbor-net
  depends_on:
    - log
    - registry
    - postgresql
    - redis
  restart: unless-stopped
portal
portal:
  image: goharbor/harbor-portal:latest
  networks:
    - harbor-net
  depends_on:
    - log
    - core
  restart: unless-stopped
jobservice
jobservice:
  image: goharbor/harbor-jobservice:latest
  volumes:
    - job_logs:/var/log/jobs:z
    - ./config/jobservice/config.yml:/etc/jobservice/config.yml:z
  networks:
    - harbor-net
  depends_on:
    - core
  restart: unless-stopped
redis
redis:
  image: goharbor/redis-photon:latest
  volumes:
    - redis_data:/var/lib/redis
  networks:
    - harbor-net
  restart: unless-stopped
trivy-adapter
trivy-adapter:
  image: goharbor/trivy-adapter-photon:latest
  environment:
    SCANNER_TRIVY_CACHE_DIR: /home/scanner/.cache/trivy
    SCANNER_TRIVY_REPORTS_DIR: /home/scanner/.cache/reports
  volumes:
    - trivy_cache:/home/scanner/.cache
  networks:
    - harbor-net
  restart: unless-stopped
proxy
proxy:
  image: goharbor/nginx-photon:latest
  ports:
    - "80:8080"
    - "443:8443"
  volumes:
    - ./config/nginx:/etc/nginx:z
  networks:
    - harbor-net
  depends_on:
    - registry
    - core
    - portal
  restart: unless-stopped

Quick Start

terminal
1# 1. Create the compose file
2cat > docker-compose.yml << 'EOF'
3services:
4 log:
5 image: goharbor/harbor-log:latest
6 volumes:
7 - harbor_log:/var/log/docker/:z
8 - ./config/log/logrotate.conf:/etc/logrotate.d/logrotate.conf:z
9 networks:
10 - harbor-net
11 restart: unless-stopped
12
13 registry:
14 image: goharbor/registry-photon:latest
15 volumes:
16 - registry_data:/storage:z
17 - ./config/registry/config.yml:/etc/registry/config.yml:z
18 networks:
19 - harbor-net
20 depends_on:
21 - log
22 restart: unless-stopped
23
24 registryctl:
25 image: goharbor/harbor-registryctl:latest
26 volumes:
27 - registry_data:/storage:z
28 - ./config/registry/config.yml:/etc/registry/config.yml:z
29 - ./config/registryctl/config.yml:/etc/registryctl/config.yml:z
30 networks:
31 - harbor-net
32 restart: unless-stopped
33
34 postgresql:
35 image: goharbor/harbor-db:latest
36 environment:
37 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
38 volumes:
39 - database:/var/lib/postgresql/data:z
40 networks:
41 - harbor-net
42 restart: unless-stopped
43
44 core:
45 image: goharbor/harbor-core:latest
46 environment:
47 CORE_KEY: ${CORE_KEY}
48 _REDIS_URL_CORE: redis://redis:6379/0
49 SYNC_REGISTRY: "false"
50 CHART_CACHE_DRIVER: redis
51 _REDIS_URL_REG: redis://redis:6379/1
52 PORTAL_URL: http://portal:8080
53 REGISTRY_URL: http://registry:5000
54 TOKEN_SERVICE_URL: http://core:8080/service/token
55 HARBOR_ADMIN_PASSWORD: ${HARBOR_ADMIN_PASSWORD}
56 DATABASE_TYPE: postgresql
57 volumes:
58 - core_data:/data:z
59 - ./config/core/app.conf:/etc/core/app.conf:z
60 networks:
61 - harbor-net
62 depends_on:
63 - log
64 - registry
65 - postgresql
66 - redis
67 restart: unless-stopped
68
69 portal:
70 image: goharbor/harbor-portal:latest
71 networks:
72 - harbor-net
73 depends_on:
74 - log
75 - core
76 restart: unless-stopped
77
78 jobservice:
79 image: goharbor/harbor-jobservice:latest
80 volumes:
81 - job_logs:/var/log/jobs:z
82 - ./config/jobservice/config.yml:/etc/jobservice/config.yml:z
83 networks:
84 - harbor-net
85 depends_on:
86 - core
87 restart: unless-stopped
88
89 redis:
90 image: goharbor/redis-photon:latest
91 volumes:
92 - redis_data:/var/lib/redis
93 networks:
94 - harbor-net
95 restart: unless-stopped
96
97 trivy-adapter:
98 image: goharbor/trivy-adapter-photon:latest
99 environment:
100 SCANNER_TRIVY_CACHE_DIR: /home/scanner/.cache/trivy
101 SCANNER_TRIVY_REPORTS_DIR: /home/scanner/.cache/reports
102 volumes:
103 - trivy_cache:/home/scanner/.cache
104 networks:
105 - harbor-net
106 restart: unless-stopped
107
108 proxy:
109 image: goharbor/nginx-photon:latest
110 ports:
111 - "80:8080"
112 - "443:8443"
113 volumes:
114 - ./config/nginx:/etc/nginx:z
115 networks:
116 - harbor-net
117 depends_on:
118 - registry
119 - core
120 - portal
121 restart: unless-stopped
122
123volumes:
124 harbor_log:
125 registry_data:
126 database:
127 core_data:
128 job_logs:
129 redis_data:
130 trivy_cache:
131
132networks:
133 harbor-net:
134 driver: bridge
135EOF
136
137# 2. Create the .env file
138cat > .env << 'EOF'
139# Harbor Admin Password
140HARBOR_ADMIN_PASSWORD=Harbor12345
141
142# PostgreSQL
143POSTGRES_PASSWORD=secure_postgres_password
144
145# Core Secret Key
146CORE_KEY=your_32_char_secret_key_here
147EOF
148
149# 3. Start the services
150docker compose up -d
151
152# 4. View logs
153docker compose logs -f

One-Liner

Run this command to download and set up the recipe in one step:

terminal
1curl -fsSL https://docker.recipes/api/recipes/harbor-registry-stack/run | bash

Troubleshooting

  • Harbor UI shows 'Internal Server Error': Check PostgreSQL connectivity and ensure database initialization completed successfully in logs
  • Docker login fails with certificate errors: Verify SSL certificates are properly configured in NGINX and trusted by Docker daemon
  • Trivy scanner shows outdated vulnerability database: Check internet connectivity and restart trivy-adapter container to force database update
  • Job service fails with Redis connection errors: Verify Redis container is healthy and check Redis URL configuration in core service environment
  • Registry push fails with 'insufficient storage': Check available disk space and configure garbage collection policies to free unused image layers
  • LDAP authentication not working: Verify LDAP server connectivity and check Harbor core logs for authentication binding errors

Community Notes

Loading...
Loading notes...

Download Recipe Kit

Get all files in a ready-to-deploy package

Includes docker-compose.yml, .env template, README, and license

Ad Space