llz's zone
云原生制品注册表Harbor
Dec 06, 2024什么是Harbor
官方定义为:“A complete OCI compliant cloud-native artifact registry”,“artifact”意为“制品”,容器镜像就是云原生开发的制品,Harbor则是完全符合OCI标准的容器镜像仓库。
PS:Helm Chart也是云原生开发的制品,因此Harbor仓库不只是可以存放容器镜像。
OCI镜像标准
其详细规范可以参考OCI image spec,其目的是为了让其他人按照这个标准创建镜像的构建和分发工具。
什么是镜像
镜像的本质,其实就是包含可执行代码的文件。镜像仓库则是提供镜像上传和下载的能力的服务器。
通过docker save命令,即可将镜像保存为文件:
$ docker pull busybox
$ docker save -o busybox.tar busybox
继续将镜像解包,看看它里面有什么:
$ mkdir busybox
$ tar -xvf busybox.tar -C busybox
$ tree busybox
busybox
├── blobs
│ └── sha256
│ ├── 3391f54c206456f4e74241be27addc5c28110e00bc5f514b5b6961917dbab998
│ ├── 770ccedf8091c5679d06a7f9d04d790c19503b76bd7ad7ad7dd055e1d95e6a91
│ ├── e49f83aa12d30427e1d2bcded8a283231d2e7e2ab408e1b0fb5ab881773c2355
│ └── f21ad18174949794e810922c8ada6ff8416aabab8ef3fd3bd144e47058359f52
├── index.json
├── manifest.json
├── oci-layout
└── repositories
镜像索引
先来看看index.json文件写了什么:
$ jq . index.json
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.index.v1+json",
"manifests": [
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:e49f83aa12d30427e1d2bcded8a283231d2e7e2ab408e1b0fb5ab881773c2355",
"size": 400,
"annotations": {
"io.containerd.image.name": "docker.io/library/busybox:latest",
"org.opencontainers.image.ref.name": "latest"
}
}
]
}
这个文件的索引能力,主要来自digest(摘要)字段:
$ jq '.manifests[0].digest' index.json
"sha256:e49f83aa12d30427e1d2bcded8a283231d2e7e2ab408e1b0fb5ab881773c2355"
通过摘要就能找到对应的文件,这种索引方式,称为“内容寻址”。摘要是文件内容的SHA256哈希值,使用同一个摘要总是能找到同样的文件内容,体现了文件内容的不可变性。
$ jq . 'blobs/'$(jq -r '.manifests[0].digest' index.json | tr : /)
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"config": {
"mediaType": "application/vnd.oci.image.config.v1+json",
"digest": "sha256:3391f54c206456f4e74241be27addc5c28110e00bc5f514b5b6961917dbab998",
"size": 390
},
"layers": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar",
"digest": "sha256:f21ad18174949794e810922c8ada6ff8416aabab8ef3fd3bd144e47058359f52",
"size": 4280320
}
]
}
与内容寻址相对的是“符号寻址”,文件内容可能发生变化,例如通过index.json这个文件名能找到对应的文件,这一过程就是符号寻址。
镜像清单
再来看看manifest.json文件写了什么:
$ jq . manifest.json
[
{
"Config": "blobs/sha256/3391f54c206456f4e74241be27addc5c28110e00bc5f514b5b6961917dbab998",
"RepoTags": [
"busybox:latest"
],
"Layers": [
"blobs/sha256/f21ad18174949794e810922c8ada6ff8416aabab8ef3fd3bd144e47058359f52"
],
"LayerSources": {
"sha256:f21ad18174949794e810922c8ada6ff8416aabab8ef3fd3bd144e47058359f52": {
"mediaType": "application/vnd.oci.image.layer.v1.tar",
"size": 4280320,
"digest": "sha256:f21ad18174949794e810922c8ada6ff8416aabab8ef3fd3bd144e47058359f52"
}
}
}
]
这个manifests.json并不是OCI image spec中规范的,而是docker将所有的清单文件内容汇总到了一起形成的文件。
镜像清单中记录了configuration和layers的摘要,可以索引到镜像配置和镜像层。
镜像配置
从镜像清单中我门找到了配置的摘要,这个配置摘要和镜像标签是一对一的,例如这里latest就是对应3391f54c...,通过配置摘要索引到镜像配置:
$ jq . blobs/sha256/3391f54c206456f4e74241be27addc5c28110e00bc5f514b5b6961917dbab998
{
"config": {
"Cmd": [
"sh"
]
},
"created": "2024-09-26T21:31:42Z",
"history": [
{
"created": "2024-09-26T21:31:42Z",
"created_by": "BusyBox 1.37.0 (glibc), Debian 12"
}
],
"rootfs": {
"type": "layers",
"diff_ids": [
"sha256:f21ad18174949794e810922c8ada6ff8416aabab8ef3fd3bd144e47058359f52"
]
},
"architecture": "arm64",
"os": "linux",
"variant": "v8"
}
可以看到配置文件最后表示了镜像的平台是linux/arm64,一般的一个镜像清单对应一个平台。
镜像层
从镜像清单中我门找到了层文件的摘要,通过层文件摘要索引到镜像层,但如果去查看层文件会发现是一堆乱码,从清单中我们可以看到这个层文件其实是tar格式的文件:
$ jq '.layers[0].mediaType' 'blobs/'$(jq -r '.manifests[0].digest' index.json | tr : /)
"application/vnd.oci.image.layer.v1.tar"
因此可以使用tar命令解包:
$ mkdir layer
$ tar -xvf f21ad181... -C layer
$ tree -L1 layer
layer
├── bin
├── dev
├── etc
├── home
├── lib
├── lib64 -> lib
├── root
├── tmp
├── usr
└── var
原来一个层文件,就是一个系统的根目录。但是busybox这个镜像只有一个层,或许一个层文件并不是一个完整的文件系统呢?我们在busybox的基础上做一些修改:
FROM busybox
RUN echo 'test layer' > /test
接着构建镜像,并在此解包,查询清单文件,可以看到有两个层:
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"config": {
"mediaType": "application/vnd.oci.image.config.v1+json",
"digest": "sha256:34c9b411c55616d73aaa3cb104807d7dfcd0ac1d829a0fb32b50ab8d8ceba960",
"size": 629
},
"layers": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar",
"digest": "sha256:f21ad18174949794e810922c8ada6ff8416aabab8ef3fd3bd144e47058359f52",
"size": 4280320
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar",
"digest": "sha256:28e61e7b8c2aa5790126c7d0ee6f97c97dc20025c5797d139e7c2d16815344c7",
"size": 3584
}
]
}
其中f21ad1817...和busybox:latest的层一样,而28e61e7b...则是新加的层文件,我们将它解包看看:
$ tree -L1 layer
layer
├── etc
├── proc
├── sys
└── test
原来不是每个层都是完整的文件系统,只有所有的层叠加在一起才是完整的文件系统,我们可以将镜像跑起来确认一下:
$ docker run busybox ls /
bin
dev
etc
home
lib
lib64
proc
root
sys
tmp
usr
var
$ docker run busybox:test ls /
bin
dev
etc
home
lib
lib64
proc
root
sys
test
tmp
usr
var
可以看到确实是在busybox:latest的基础上创建了test文件,镜像多个一个层,记录了这个增量的修改。
PS:Dockerfile中,
RUN、ADD、COPY命令会创建新的层,其余命令会修改镜像配置。
DockerArchive转换为OCI格式
我们最开始得到的是docker的镜像格式:
$ tree busybox
busybox
├── blobs
│ └── sha256
│ ├── 3391f54c... # 配置
│ ├── 770ccedf...
│ ├── e49f83aa... # 清单
│ └── f21ad181... # 层
├── index.json # 索引
├── manifest.json # 清单汇总
├── oci-layout # 格式版本
└── repositories # 镜像名称和摘要
oci-layout文件记录了镜像格式对应的版本。
$ cat oci-layout | jq
{
"imageLayoutVersion": "1.0.0"
}
repositories文件记录了镜像的对应的摘要,这个文件也不是OCI image spec要求的。
$ cat repositories | jq
{
"busybox": {
"latest": "f21ad18174949794e810922c8ada6ff8416aabab8ef3fd3bd144e47058359f52"
}
还剩一个没看的770ccedf...文件,这也是一个配置文件,是docker构建镜像过程中的中间产物,最终的镜像配置以实际索引到的为准。
使用skopeo可以将docker archive转换为OCI镜像格式:
$ skopeo copy docker-archive:busybox.tar oci:busybox_oci
$ tree busybox_oci
busybox_oci
├── blobs
│ └── sha256
│ ├── 0f1a7ba9... # 配置
│ ├── 1933e30a... # 层
│ └── aa5d684e... # 清单
├── index.json # 索引
└── oci-layout # 格式版本
Harbor的架构
Harbor本身是一套微服务,其中核心的仓库功能,使用的是Docker开源的方案。在此基础上,又有其他的服务,提供如多租户、漏洞扫描等企业级功能,因此各大公有云厂商的镜像服务都基于Harbor实现。
整体架构图如下:

可以看到,Harbor的接入层由nginx实现,也就是说Harbor从外部看,就是一个http服务。
图中的Harbor组件有这些:
- Web Portal:提供用户操作界面
- Core:核心逻辑
- GC Controller:垃圾回收
- Log Collector:日志收集
- Job Service:任务管理
图中的Harbor的依赖组件有这些:
- Nginx:提供代理服务
- Chart Museum:用作Helm Chart仓库
- Notary:摘要计算和验证
- Distribution:用作镜像仓库
- Redis:缓存服务
- Storage:镜像存储,可以是块存储、文件系统、对象存储
- PostgreSQL:数据库,存储元数据
- Jaeger:提供Tracing能力
- Prometheus:提供监控&可观测能力
还有一些以插件形式存在的组件。最核心需要掌握的有两个:Harbor-Core和Distribution,也是使用Harbor最常用到的。
源码编译 & 构建镜像 & 本地部署
这里以harbor 2.7.4为例进行编译,这是最后一个支持HelmChart的habor版本,本地是Apple M2的芯片。虽然官方提供了编译文档,但是没有很好的适配arm64架构,所以在Apple芯片上编译会有一些问题。
本小节所有命令,在harbor源码根目录下执行。
下载harbor源码
git clone https://github.com/goharbor/harbor.git
git checkout v2.7.4
git switch -c v2.7.4 # 基于2.7.4版本创建一个新的分支
编写配置文件
配置文件说明参考本文附录。
cp make/harbor.yml.tmpl make/harbor.yml
生成api代码
这个命令就是使用go-swagger从/api/v2.0/swagger.yaml生成go代码:
make gen_apis
这里由于本地是arm64会报错,需要做如下修改后再执行:
# 1. Makefile文件,GOBUILDIMAGE=goharbor/golang:$(GOVERSION),替换为GOBUILDIMAGE=golang:$(GOVERSION)
# 原因是goharbor/golang镜像中没有arm64的版本
# 2. Makefile文件,SPECTRAL_VERSION=v6.1.0,替换为SPECTRAL_VERSION=v6.14.2
# 原因是6.1.0没有arm64的版本
# 3. tools/spectral/Dockerfile文件,下载地址spectral-linux替换为spectral-linux-arm64
# 4. tools/swagger/Dockerfile文件,下载地址swagger_linux_amd64替换为swagger-linux-arm64
生成的代码在src/server/v2.0目录下。
检查编译环境
这个命令会去检查本地的golang、docker、docker-compose版本:
make check_environment
设置依赖组件版本
包括distribution、trivy、trivy-adapter、chartmuseum这些依赖组件。
make versions_prepare
正常这个命令不会有输出,可以编辑Makefile文件,把versions_prepare修改为:
versions_prepare:
@echo $$VERSIONS_FOR_PREPARE
echo "$$VERSIONS_FOR_PREPARE" > $(MAKE_PREPARE_PATH)/$(PREPARE_VERSION_NAME)
如此make versions_prepare输出:
VERSION_TAG: dev REGISTRY_VERSION: v2.8.0-patch-redis NOTARY_VERSION: v0.6.1 TRIVY_VERSION: v0.46.1 TRIVY_ADAPTER_VERSION: v0.30.18 CHARTMUSEUM_VERSION: v0.14.0-redis
echo "$VERSIONS_FOR_PREPARE" > /Users/lixiang97/go/src/github.com/goharbor/harbor/make/photon/prepare/versions
这个命令的作用就是,把依赖组件的版本写入到make/photon/prepare/versions文件中。
编译core
make compile_core
这个命令先执行make gen_apis,由于我们之前已经执行过了,可以从makefile里去掉:
# compile_core: gen_apis
compile_core:
@echo "compiling binary for core (golang image)..."
@echo $(GOBUILDPATHINCONTAINER)
# 去掉@,显示执行过程
# @$(DOCKERCMD) run --rm -v $(BUILDPATH):$(GOBUILDPATHINCONTAINER) -w $(GOBUILDPATH_CORE) $(GOBUILDIMAGE) $(GOIMAGEBUILD_CORE) -o $(GOBUILDPATHINCONTAINER)/$(GOBUILDMAKEPATH_CORE)/$(CORE_BINARYNAME)
$(DOCKERCMD) run --rm -v $(BUILDPATH):$(GOBUILDPATHINCONTAINER) -w $(GOBUILDPATH_CORE) $(GOBUILDIMAGE) $(GOIMAGEBUILD_CORE) -o $(GOBUILDPATHINCONTAINER)/$(GOBUILDMAKEPATH_CORE)/$(CORE_BINARYNAME)
@echo "Done."
命令输出为:
compiling binary for core (golang image)...
/harbor
/usr/local/bin/docker run --rm -v /Users/lixiang97/go/src/github.com/goharbor/harbor:/harbor -w /harbor/src/core golang:1.21.4 /usr/local/go/bin/go build -mod vendor -buildvcs=false --ldflags "-w -s -X github.com/goharbor/harbor/src/pkg/version.GitCommit=f4e08e2a -X github.com/goharbor/harbor/src/pkg/version.ReleaseVersion=v2.7.4" -o /harbor/make/photon/core/harbor_core
Done.
这个命令会把编译的harbor_core二进制文件放在make/photon/core目录下。
编译jobservice
make compile_jobservice
这个命令会把编译的harbor_jobservice二进制文件放在make/photon/jobservice目录下。
编译registryctl
make compile_registryctl
这个命令会把编译的harbor_registryctl二进制文件放在make/photon/registryctl目录下。
编译migrate_patch
make compile_notary_migrate_patch
这个命令会把编译的migrate-patch二进制文件放在make/photon/notary目录下。
构建prepare镜像
make -f make/photon/Makefile _build_prepare \
-e BUILD_BASE=true \
-e BASEIMAGETAG=dev \
-e PULL_BASE_FROM_DOCKERHUB=false \
-e VERSIONTAG=dev
注意这里PULL_BASE_FROM_DOCKERHUB不能是true,否则会去dockerhub拉取镜像,那里只有amd64架构的。
这个命令会按如下两个命令,构建出两个镜像:
# BUILD_BASE=true时会构建该镜像
# harbor-prepare-base镜像tag为BASEIMAGETAG
/usr/local/bin/docker build --no-cache -f make/photon/prepare/Dockerfile.base -t goharbor/harbor-prepare-base:dev --label base-build-date=20250107 .
# PULL_BASE_FROM_DOCKERHUB=false使用本地刚构建的harbor-prepare-base镜像
# prepare镜像的tag为VERSIONTAG
/usr/local/bin/docker build --no-cache --pull=false --build-arg harbor_base_image_version=dev --build-arg harbor_base_namespace=goharbor -f make/photon/prepare/Dockerfile -t goharbor/prepare:dev .
查看本地镜像列表:
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
# prepare基于harbor-prepare-base,将make/photon/prepare目录下的python项目,copy到了镜像中
goharbor/prepare dev 6b2ef89246ec 38 seconds ago 208MB
# harbor-prepare-base基于photon,安装了一些必备工具
goharbor/harbor-prepare-base dev 3f1f1a9843f4 45 seconds ago 162MB
构建pgsql镜像
make -f make/photon/Makefile _build_db \
-e BUILD_BASE=true \
-e BASEIMAGETAG=dev \
-e PULL_BASE_FROM_DOCKERHUB=false \
-e VERSIONTAG=dev
这个命令会按如下两个命令,构建出两个镜像:
/usr/local/bin/docker build --no-cache -f make/photon/db/Dockerfile.base -t goharbor/harbor-db-base:dev --label base-build-date=20250107 .
/usr/local/bin/docker build --no-cache --pull=false --build-arg harbor_base_image_version=dev --build-arg harbor_base_namespace=goharbor -f make/photon/db/Dockerfile -t goharbor/harbor-db:dev .
这里构建harbor-db-base的时候会报错,编辑make/photon/db/Dockerfile.base修改为:
RUN tdnf install -y shadow gzip postgresql13 findutils bc >> /dev/null \
# 这里group已存在
# && groupadd -r postgres --gid=999 \
&& groupadd -r postgres --gid=999 || true \
# 这里user已存在
# && useradd -m -r -g postgres --uid=999 postgres \
&& useradd -m -r -g postgres --uid=999 postgres || true \
查看本地镜像列表:
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
# harbor-db初始化表结构等
goharbor/harbor-db dev 48f3fbd04894 About a minute ago 169MB
# 基于photon构建pgsql13镜像
goharbor/harbor-db-base dev 3df28325014c About a minute ago 169MB
构建portal镜像
make -f make/photon/Makefile _build_portal \
-e BUILD_BASE=true \
-e BASEIMAGETAG=dev \
-e PULL_BASE_FROM_DOCKERHUB=false \
-e VERSIONTAG=dev
这个命令会按如下两个命令,构建出两个镜像:
/usr/local/bin/docker build --no-cache -f make/photon/portal/Dockerfile.base -t goharbor/harbor-portal-base:dev --label base-build-date=20250107 .
/usr/local/bin/docker build --no-cache --pull=false --build-arg harbor_base_image_version=dev --build-arg harbor_base_namespace=goharbor --build-arg npm_registry= -f make/photon/portal/Dockerfile -t goharbor/harbor-portal:dev .
查看本地镜像列表:
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
# 基于node和harbor-portal-base构建portal镜像
goharbor/harbor-portal dev 4d8d07c13c9f 35 seconds ago 125MB
# 基于photon构建nginx镜像
goharbor/harbor-portal-base dev 569cd73f95e4 2 minutes ago 116MB
构建core镜像
make -f make/photon/Makefile _build_core \
-e BUILD_BASE=true \
-e BASEIMAGETAG=dev \
-e PULL_BASE_FROM_DOCKERHUB=false \
-e VERSIONTAG=dev
这个命令会按如下两个命令,构建出两个镜像:
/usr/local/bin/docker build --no-cache -f make/photon/core/Dockerfile.base -t goharbor/harbor-core-base:dev --label base-build-date=20250107 .
/usr/local/bin/docker build --no-cache --pull=false --build-arg harbor_base_image_version=dev --build-arg harbor_base_namespace=goharbor -f make/photon/core/Dockerfile -t goharbor/harbor-core:dev .
查看本地镜像列表:
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
goharbor/harbor-core dev 34deb90a3320 45 seconds ago 220MB
goharbor/harbor-core-base dev e699127e38d8 48 seconds ago 46.4MB
构建jobservice镜像
make -f make/photon/Makefile _build_jobservice \
-e BUILD_BASE=true \
-e BASEIMAGETAG=dev \
-e PULL_BASE_FROM_DOCKERHUB=false \
-e VERSIONTAG=dev
这个命令会按如下两个命令,构建出两个镜像:
/usr/local/bin/docker build --no-cache -f make/photon/jobservice/Dockerfile.base -t goharbor/harbor-jobservice-base:dev --label base-build-date=20250107 .
/usr/local/bin/docker build --no-cache --pull=false --build-arg harbor_base_image_version=dev --build-arg harbor_base_namespace=goharbor -f make/photon/jobservice/Dockerfile -t goharbor/harbor-jobservice:dev .
查看本地镜像列表:
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
goharbor/harbor-jobservice dev 1c90cae3892e 22 seconds ago 274MB
goharbor/harbor-jobservice-base dev b573d990857d 24 seconds ago 46.4MB
构建log镜像
make -f make/photon/Makefile _build_log \
-e BUILD_BASE=true \
-e BASEIMAGETAG=dev \
-e PULL_BASE_FROM_DOCKERHUB=false \
-e VERSIONTAG=dev
这个命令会按如下两个命令,构建出两个镜像:
/usr/local/bin/docker build --no-cache -f make/photon/log/Dockerfile.base -t goharbor/harbor-log-base:dev --label base-build-date=20250107 .
/usr/local/bin/docker build --no-cache --pull=false --build-arg harbor_base_image_version=dev --build-arg harbor_base_namespace=goharbor -f make/photon/log/Dockerfile -t goharbor/harbor-log:dev .
查看本地镜像列表:
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
goharbor/harbor-log dev ff4d9e48c5fa 31 seconds ago 127MB
goharbor/harbor-log-base dev 81f2a5a06b6a 33 seconds ago 127MB
构建nginx镜像
make -f make/photon/Makefile _build_nginx \
-e BUILD_BASE=true \
-e BASEIMAGETAG=dev \
-e PULL_BASE_FROM_DOCKERHUB=false \
-e VERSIONTAG=dev
这个命令会按如下两个命令,构建出两个镜像:
/usr/local/bin/docker build --no-cache -f make/photon/nginx/Dockerfile.base -t goharbor/harbor-nginx-base:dev --label base-build-date=20250107 .
/usr/local/bin/docker build --no-cache --pull=false --build-arg harbor_base_image_version=dev --build-arg harbor_base_namespace=goharbor -f make/photon/nginx/Dockerfile -t goharbor/nginx-photon:dev .
查看本地镜像列表:
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
goharbor/harbor-nginx-base dev 9777a81bf63a 49 seconds ago 116MB
goharbor/nginx-photon dev 41fb831783b8 49 seconds ago 116MB
构建registry镜像
make -f make/photon/Makefile _build_registry \
-e BUILD_BASE=true \
-e BASEIMAGETAG=dev \
-e PULL_BASE_FROM_DOCKERHUB=false \
-e VERSIONTAG=dev \
-e BUILDBIN=true \
-e REGISTRY_SRC_TAG=v2.8.0
其中BUILDBIN=true表示本地拉取distribution源码,基于REGISTRY_SRC_TAG构建。具体过程在make/photon/registry/builder脚本中。这个脚本通过git apply添加一些代码到distribution源码中。
查看本地镜像列表:
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
goharbor/registry-photon dev 66e96a2cbca5 13 seconds ago 80.1MB
goharbor/harbor-registry-base dev ec78ec83b388 About a minute ago 44.6MB
构建registryctl镜像
make -f make/photon/Makefile _build_registryctl \
-e BUILD_BASE=true \
-e BASEIMAGETAG=dev \
-e PULL_BASE_FROM_DOCKERHUB=false \
-e VERSIONTAG=dev
查看本地镜像列表:
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
goharbor/harbor-registryctl dev ac4ae05f0e41 2 minutes ago 138MB
goharbor/harbor-registryctl-base dev 192e77d51d12 2 minutes ago 44.6MB
构建trivy-adapter镜像
make -f make/photon/Makefile _build_trivy_adapter \
-e BUILD_BASE=true \
-e BASEIMAGETAG=dev \
-e PULL_BASE_FROM_DOCKERHUB=false \
-e VERSIONTAG=dev \
-e TRIVYFLAG=true \
-e TRIVYVERSION=v0.46.1 \
-e BUILDBIN=true \
-e TRIVYADAPTERVERSION=v0.30.18 \
-e TRIVY_DOWNLOAD_URL=https://github.com/aquasecurity/trivy/releases/download/v0.46.1/trivy_0.46.1_Linux-64bit.tar.gz
BUILDBIN=true表示本地clone构建trivy-adapter二进制文件,trivy还是需要直接下载。本地clone构建trivy-adapter的逻辑在make/photon/trivy-adapter/builder.sh中。
查看本地镜像列表:
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
goharbor/trivy-adapter-photon dev dcb8a48d4d16 19 seconds ago 467MB
goharbor/harbor-trivy-adapter-base dev 2ff7e3732d32 About a minute ago 45MB
构建redis镜像
make -f make/photon/Makefile _build_redis \
-e BUILD_BASE=true \
-e BASEIMAGETAG=dev \
-e PULL_BASE_FROM_DOCKERHUB=false \
-e VERSIONTAG=dev
查看本地镜像列表:
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
goharbor/redis-photon dev 43fd89318b4d 4 minutes ago 119MB
goharbor/harbor-redis-base dev 8c129a3a51bc 4 minutes ago 119MB
构建chart-server镜像
make -f make/photon/Makefile _build_chart_server \
-e BUILD_BASE=true \
-e BASEIMAGETAG=dev \
-e PULL_BASE_FROM_DOCKERHUB=false \
-e VERSIONTAG=dev \
-e CHARTFLAG=true \
-e BUILDBIN=true \
-e GOBUILDIMAGE=golang:1.21.4 \
-e CHARTMUSEUM_SRC_TAG=v0.14.0 \
-e DOCKERIMAGENAME_CHART_SERVER=goharbor/chartmuseum-photon
查看本地镜像列表:
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
goharbor/chartmuseum-photon dev 5f9ad5a5832c 6 seconds ago 238MB
goharbor/harbor-chartserver-base dev 54070b204d0b 4 minutes ago 44.6MB
构建exporter镜像
make -f make/photon/Makefile _compile_and_build_exporter \
-e BUILD_BASE=true \
-e BASEIMAGETAG=dev \
-e PULL_BASE_FROM_DOCKERHUB=false \
-e VERSIONTAG=dev \
-e BASEIMAGETAG=dev \
-e GOBUILDIMAGE=golang:1.21.4
查看本地镜像列表:
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
goharbor/harbor-exporter dev 631fe20b4497 6 seconds ago 99MB
goharbor/harbor-exporter-base dev d0f7bc604dc2 11 seconds ago 46.4MB
部署前准备
make prepare -e TRIVYFLAG=true -e CHARTFLAG=true
这个命令首先会执行:
/usr/bin/sed -i '' -e 's/goharbor\/prepare:.*[[:space:]]\+/goharbor\/prepare:dev prepare /' make/prepare
作用是把make/prepare脚本中的prepare镜像替换为之前构建的镜像。
接着执行:
make/prepare --conf /compose_location/harbor.yml --with-trivy --with-chartmuseum
这个脚本会把make/harbor.yml拷贝出来,找到data_volume,接着使用prepare镜像在data_volume里创建如下内容:
% tree
.
├── ca_download
├── chart_storage
├── database
├── job_logs
├── redis
├── registry
├── secret
│ ├── core
│ │ └── private_key.pem
│ ├── keys
│ │ └── secretkey
│ └── registry
│ └── root.crt
└── trivy-adapter
├── reports
└── trivy
14 directories, 3 files
以及在make/common/config目录下创建如下内容,包含各个组件的配置,有的是文件形式,有的是环境变量形式。
tree make/common/config
make/common/config
├── chartserver
│ └── env
├── core
│ ├── app.conf
│ ├── certificates
│ └── env
├── db
│ └── env
├── jobservice
│ ├── config.yml
│ └── env
├── log
│ ├── logrotate.conf
│ └── rsyslog_docker.conf
├── nginx
│ ├── conf.d
│ └── nginx.conf
├── portal
│ └── nginx.conf
├── registry
│ ├── config.yml
│ └── passwd
├── registryctl
│ ├── config.yml
│ └── env
├── shared
│ └── trust-certificates
└── trivy-adapter
└── env
15 directories, 15 files
以及在make目录下生成docker-compose.yml文件,用于docker-compose部署。
本地部署
make start
这个命令就是使用上一步创建的docker-compose.yml文件来部署。看到如下输出,即为部署成功:
Start complete. You can visit harbor now.
如果出问题了,可以make restart重新部署。
浏览器访问localhost即可进入Harbor控制台。
附录
Harbor配置文件说明
必选参数
| 配置 | 参数 | 描述 |
|---|---|---|
| hostname | Harbor服务域名。 | |
| http | port | HTTP的端口号。默认80。 |
| https | port | HTTPS的端口号。默认443。 |
| certificate | SSL证书的路径。 | |
| private_key | SSL密钥的路径。 | |
| internal_tls | enable | 启用内部组件HTTPS通信。 |
| dir | 包含内部证书和密钥的目录路径。 | |
| harbor_admin_password | 系统管理员初始密码。 | |
| database | 本地数据库配置。选择配置外部数据库时禁用此选项。 | |
| password | root密码。 | |
| max_idle_conns | 空闲连接池中的最大连接数。 | |
| max_open_conns | 数据库的最大打开连接数。 | |
| data_volume | 指定用于存储Harbor数据的目标主机位置。 | |
| trivy | 配置Trivy扫描器。 | |
| ignore_unfixed | 设置为true以仅显示已修复的漏洞。默认false。 | |
| skip_update | 是否从github更新漏洞库。默认false。 | |
| insecure | 设置为true以跳过验证注册表证书。默认false。 | |
| github_token | 指定gitHub访问令牌提高访问速率。 | |
| jobservice | max_job_workers | worker最大数量。默认10。 |
| notification | webhook_job_max_retry | webhook最大重试次数。默认10。 |
| chart | absolute_url | 设置为enabled使Chart使用绝对URL。 |
| log | Harbor使用rsyslog收集每个容器的日志。 | |
| level | debug、info、warning、error或fatal。默认info。 | |
| local | 设置日志保留参数。 | |
| external_endpoint | 启用此选项以将日志转发到syslog服务器。 | |
| proxy | 配置trivy-adapter、复制作业服务和Harbor使用的代理。如果不需要代理留空。 | |
| http_proxy | 配置HTTP代理。 | |
| https_proxy | 配置HTTPS代理。 | |
| no_proxy | 配置哪些情况下不使用代理。 |
可选参数
| 配置 | 参数 | 描述 |
|---|---|---|
| external_url | 外部代理地址。启用后hostname不再生效。 | |
| storage_service | 使用外部存储而不是主机数据卷。 | |
| ca_bundle | CA根证书位置。 | |
| filesystem | 这里默认是文件系统,也可以是s3等。 | |
| redirect | disable/enable,是否禁用注册表重定向。 | |
| external_database | 外部pgSQL数据库。 | |
| harbor | harbor使用的库。 | |
| notary_signer | notary signer使用的库。 | |
| notary_server | notary server使用的库。 | |
| external_redis | 外部redis数据库。 | |
| host | redisHost:redisPort,哨兵模式多个地址使用逗号分隔。 | |
| sentinel_master_set | 哨兵模式时设置。 | |
| password | redis密码。 | |
| registry_db_index | 服务隔离,registry用的索引号。 | |
| jobservice_db_index | 服务隔离,jobservice用的索引号。 | |
| chartmuseum_db_index | 服务隔离,chartmuseum用的索引号。 | |
| trivy_db_index | 服务隔离,trivy用的索引号。 | |
| metric | 指标配置。 | |
| enabled | 是否暴露指标,默认false。 | |
| port | 端口。默认9090。 | |
| path | 路径。默认/metrics。 |
配置文件参考
hostname: harbor.su.com
http:
port: 80
harbor_admin_password: Harbor12345
database:
password: root123
max_idle_conns: 100
max_open_conns: 900
conn_max_lifetime: 5m
conn_max_idle_time: 0
data_volume: /usr/local/harbor-data
trivy:
ignore_unfixed: false
skip_update: false
offline_scan: false
security_check: vuln
insecure: false
jobservice:
max_job_workers: 10
notification:
webhook_job_max_retry: 10
chart:
absolute_url: disabled
log:
level: info
local:
rotate_count: 50
rotate_size: 200M
location: /var/log/harbor
_version: 2.7.0
proxy:
http_proxy:
https_proxy:
no_proxy:
components:
- core
- jobservice
- trivy
upload_purging:
enabled: true
age: 168h
interval: 24h
dryrun: false
cache:
enabled: false
expire_hours: 24