Skip to content

Latest commit

 

History

History
234 lines (184 loc) · 9.43 KB

File metadata and controls

234 lines (184 loc) · 9.43 KB

Harbor Development Environment

This directory contains all configuration files needed to run Harbor locally for development.

Philosophy

Containerized with Hot Reload: All Harbor services run in Docker containers with Air hot reload. Services communicate via Docker network - no localhost issues.

Quick Start

# Start full dev environment (includes OpenAPI UI)
task dev:up

# Start infrastructure only (for native development)
task dev:infra:up

Architecture

All services run in containers:

  • Core - Harbor API with Air hot reload (port 8080, Delve 2345)
  • JobService - Background jobs with Air hot reload (port 8888, Delve 2346)
  • RegistryCtl - Registry controller with Air hot reload (port 8085, Delve 2347)
  • Trivy Adapter - Vulnerability scanner (port 8081)
  • PostgreSQL - Database (port 5432)
  • Redis/Valkey - Cache/queue (port 6379)
  • Distribution - Docker Registry (port 50000)
                    ┌────────────────────────────────────────┐
                    │            Docker Network              │
                    │                                        │
┌──────────┐        │  ┌──────┐  ┌───────────┐  ┌───────┐    │
│  Portal  │◄───────┼─►│ Core │◄─│ JobService│◄─│ Trivy │    │
│ :4200    │        │  │:8080 │  │   :8888   │  │ :8081 │    │
└──────────┘        │  └──┬───┘  └─────┬─────┘  └───────┘    │
   (native)         │     │            │                     │
                    │  ┌──▼────────────▼──┐                  │
                    │  │    PostgreSQL    │                  │
                    │  │      :5432       │                  │
                    │  └──────────────────┘                  │
                    │  ┌──────────────────┐                  │
                    │  │      Redis       │                  │
                    │  │      :6379       │                  │
                    │  └──────────────────┘                  │
                    │  ┌──────────────────┐                  │
                    │  │    Registry      │                  │
                    │  │     :50000       │                  │
                    │  └──────────────────┘                  │
                    └────────────────────────────────────────┘

Directory Structure

devenv/
├── docker-compose.yml         # All services (infra + backend + trivy)
├── air.core.toml              # Air hot-reload config for Core
├── air.jobservice.toml        # Air hot-reload config for JobService
├── air.registryctl.toml       # Air hot-reload config for RegistryCtl
├── registry.passwd            # Registry HTTP basic auth credentials
├── token_service_key.pem      # Generated RSA key for token signing
└── README.md                  # This file

config/                        # Canonical service configs (shared by dev + compose)
├── jobservice.yml             # JobService configuration
├── registry.yml               # Docker Registry config
├── registryctl.yml            # RegistryCtl configuration
├── nginx/                     # Reverse proxy + TLS (compose only)
└── portal/nginx.conf          # Baked into portal image at build time

dockerfile/
└── dev.core.dockerfile        # Dev image with Go, Air, and Delve

Development Commands

Full Environment

task dev:up                    # Start everything (Core, JobService, Trivy, Portal)
task dev:up SKIP_TRIVY=true    # Start without Trivy
task dev:status          # Show running containers
task dev:logs            # View all container logs
task dev:clean           # Stop everything and remove volumes

Backend Only

task dev:backend:up              # Start Core + JobService containers
task dev:backend:down            # Stop backend containers
task dev:backend:logs            # View backend logs
task dev:backend:logs:<service>  # View logs for core, jobservice, or registryctl
task dev:backend:restart         # Restart backend containers

Infrastructure Only

task dev:infra:up        # Start PostgreSQL, Redis, Registry
task dev:infra:down      # Stop infrastructure
task dev:infra:remove    # Remove with volumes

Frontend

task dev:frontend:native     # Start Angular with HMR (runs natively)
task dev:frontend:build      # Build frontend for production
task dev:frontend:test       # Run frontend tests in watch mode
task dev:frontend:test:once  # Run frontend tests once

Database

task dev:db:shell        # Open PostgreSQL shell
task dev:db:migrate      # Run migrations
task dev:db:reset        # Reset to clean state (shows [y/N] prompt)

Utilities

task dev:gen:private-key # Generate RSA private key for token signing
task dev:info            # Show current SLOT and port assignments
task dev:logs            # View all container logs

Build & Test (see main README)

task build               # Build all binaries
task build:gen-apis      # Generate API server code from OpenAPI spec
task test                # Run all tests
task test:lint           # Run Go linters
task test:unit           # Run Go unit tests
task test:quick          # Quick validation (fast checks only)

Hot Reload

Code changes are automatically detected and rebuilt:

  • Go files: Air watches src/ and rebuilds (~3 seconds)
  • Frontend: Angular HMR (< 1 second once initial compile is complete)
  • OpenAPI UI: Swagger UI assets are built in the background during portal startup

Volume mounts with VirtioFS (Docker Desktop 4.x+) provide fast file system event propagation.

Debugging

All Go services run under Delve with --continue (no need to wait for debugger attach). Host port mappings are commented out by default to save resources — uncomment them in docker-compose.yml when needed:

  • Core: container :2345 → host ${PORT_DEBUG_CORE:-2345} (commented out)
  • JobService: container :2346 → host :2346 (commented out)
  • RegistryCtl: container :2347 → host ${PORT_DEBUG_REGISTRYCTL:-2347} (active)

To enable Core/JobService debugging, uncomment the port mappings in devenv/docker-compose.yml and restart.

Service URLs

Service URL
Portal http://localhost:4200/
API http://localhost:8080/api/v2.0
JobService http://localhost:8888
Trivy http://localhost:8081
Registry http://localhost:50000

Credentials

  • Harbor Admin: admin / Harbor12345
  • PostgreSQL: postgres / root123

Pushing Images to Harbor

Once the dev environment is running, you can push container images to test the full workflow.

Docker Desktop Configuration

Add localhost:8080 to your Docker daemon's insecure registries. In Docker Desktop, go to Settings > Docker Engine and add:

{
  "insecure-registries": [
    "localhost:8080"
  ]
}

Restart Docker Desktop after making this change.

Push Workflow

# 1. Log in to Harbor (default admin credentials)
docker login localhost:8080 -u admin -p Harbor12345

# 2. Tag an image for Harbor (images go into projects, "library" is the default)
docker pull hello-world
docker tag hello-world:latest localhost:8080/library/hello-world:latest

# 3. Push the image
docker push localhost:8080/library/hello-world:latest

# 4. Verify via API
curl -s -u admin:Harbor12345 http://localhost:8080/api/v2.0/projects/library/repositories | python3 -m json.tool

# 5. Pull it back
docker pull localhost:8080/library/hello-world:latest

Notes

  • The library project is created automatically during database migration and is public by default.
  • All images must be pushed to a project: localhost:8080/<project>/<image>:<tag>.
  • You can create additional projects via the Portal at http://localhost:4200 or the API.
  • If using a non-default SLOT (e.g., SLOT=1), the Core port shifts accordingly (e.g., 8180). Update the insecure-registries entry to match.
  • Pushing via Portal port (4200) does not work. Harbor Core sets EXT_ENDPOINT to its internal Docker hostname (core:8080), so the WWW-Authenticate token realm in /v2/ responses points to core:8080, which the host Docker client cannot resolve. Always push directly to the Core port (8080).

Troubleshooting

First-time startup is slow

The first run downloads Go modules and builds the dev image. Subsequent runs use cached layers.

Container can't find modules

The Go module cache is persisted in a Docker volume (go-mod-cache). If you see module errors, try:

task dev:clean
task dev:up

Port already in use

Check for existing processes:

lsof -i :8080   # Core
lsof -i :8888   # JobService
lsof -i :4200   # Portal