harbor 的安装和使用,主要是学习自签名证书。

一、环境准备

二、证书体系学习

2.1 角色

CA(签字的人):有一把私钥用来”签字”,有一张根证书(公开)告诉别人”这是我的签名长什么样”。它自己给自己签一张证书,这就叫”自签名根证书”。

服务端(Harbor):要证明”我就是 harbor.lab.local”。它自己生成一把私钥,写一份申请书(CSR,里面注明我要哪个域名),拿给 CA 签。CA 签完,给它一张服务端证书。

客户端(docker / containerd / k8s):连 Harbor 时,Harbor 把服务端证书亮出来。客户端只问两件事——这证书是不是我信任的 CA 签的?上面的域名对不对?两个都对就放行。

让我把这三者的关系画出来,”乱”的感觉一大半来自没看清谁信任谁、签发和信任是两个相反方向:

这张图能消掉”乱”感的关键,是看清两个方向相反的关系——证书是 CA 往下”签发”的,而信任是客户端往上建立的。这两件事一对应上,整个体系就立住了:

flowchart TD
    A["私有根证书 <br>(Private Root CA)"]
    B["Harbor 服务端证书 <br>(Harbor Server Cert)"]
    C["客户端 / Docker 守护进程 <br>(Client / Docker Daemon)"]

    %% 节点连接关系
    A --> B
    B --> C
    C -.-> A

    %% 节点颜色样式还原
    style A fill:#eeecfc,stroke:#b6b2ec,stroke-width:1.5px,color:#333
    style B fill:#e4f6f0,stroke:#a3d9ca,stroke-width:1.5px,color:#333
    style C fill:#fbf0ea,stroke:#d9b4a4,stroke-width:1.5px,color:#333

    %% 连线颜色与样式还原
    linkStyle 0 stroke:#5c5cd6,stroke-width:1.5px;
    linkStyle 1 stroke:#8c8c8c,stroke-width:1.5px;
    linkStyle 2 stroke:#b35942,stroke-width:1.5px;

2.2 建你自己的 Root CA(一次性)

1
2
3
4
5
6
# CA 私钥(这把钥匙是命根子,泄露了别人就能冒充你签证书)
openssl genrsa -out ca.key 4096

# 用 CA 私钥给自己签一张根证书(自签名)
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 \
-subj "/CN=My Lab Root CA" -out ca.crt

现在你手里有两个文件:ca.key(私钥,绝不外传)和 ca.crt(根证书,要发给所有客户端)。

2.3 给 Harbor 签一张服务端证书

1
2
3
4
5
6
7
8
9
10
# Harbor 自己的私钥
openssl genrsa -out harbor.key 4096

# 生成 CSR(申请书,注明我要 harbor.lab.local 这个域名)
openssl req -new -key harbor.key -subj "/CN=harbor.lab.local" -out harbor.csr

# 用 CA 来签这份申请——注意 SAN,这是最大的坑
openssl x509 -req -in harbor.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out harbor.crt -days 825 -sha256 \
-extfile <(printf "subjectAltName=DNS:harbor.lab.local,IP:192.168.1.50")

这里 90% 的人会栽:现代客户端(docker、containerd 都是 Go 写的)只认 SAN(Subject Alternative Name),完全不看 CN。如果你签证书时没带 subjectAltName,客户端会直接报 x509: certificate relies on legacy Common Name field。所以上面那行 -extfile 里的 DNS 和 IP 必须写全你会用来访问 Harbor 的地址。记住这一条,能省你后面几小时的抓狂。

825 days 是因为现代系统对服务端证书有效期有上限(早年是 825 天,新的甚至卡到 398 天)。学习环境其实无所谓,但知道有这回事是个加分项。

2.4 Harbor 用这张证书

1
vim harbor.yml
1
2
3
4
5
hostname: harbor.lab.local
https:
port: 443
certificate: /data/cert/harbor.crt
private_key: /data/cert/harbor.key

2.5 客户端信任

最省事的是塞进系统信任库,docker 和 containerd 都会跟着系统走,一次搞定

1
2
3
4
# Ubuntu/Debian
sudo cp ca.crt /usr/local/share/ca-certificates/lab-ca.crt
sudo update-ca-certificates
# RHEL/CentOS 系: cp 到 /etc/pki/ca-trust/source/anchors/ 然后 update-ca-trust

让 docker 单独信任某个仓库,用它的专属目录(不影响系统其他部分)

1
2
3
sudo mkdir -p /etc/docker/certs.d/harbor.lab.local
sudo cp ca.crt /etc/docker/certs.d/harbor.lab.local/ca.crt
# 注意:非 443 端口要写成目录名 harbor.lab.local:5000

containerd / k8s 的话,要么走上面的系统信任库(最简单),要么用 /etc/containerd/certs.d/hosts.toml(需要先在 containerd 配置里开 config_path)。学习阶段建议先用系统信任库,把链路跑通了再研究 containerd 的精细配置。

三、下载安装

3.1 下载

1
wget https://github.com/goharbor/harbor/releases/download/v2.14.1/harbor-offline-installer-v2.14.1.tgz

3.2 解压软件

  1. 创建工作目录
1
mkdir -p /opt/softwares
  1. 解压
1
tar -xf harbor-offline-installer-v2.14.1.tgz -C /opt/softwares
  1. 进入目录
1
cd /opt/softwares/harbor

3.3 自签名证书

  1. 创建证书的工作目录,并进入
1
2
mkdir -pv /opt/softwares/harbor/certs/{ca,server,client}
cd /opt/softwares/harbor/certs
  1. 根证书
1
2
3
4
5
6
# CA 私钥(这把钥匙是命根子,泄露了别人就能冒充你签证书)
openssl genrsa -out ca/ca.key 4096

# 用 CA 私钥给自己签一张根证书(自签名)
openssl req -x509 -new -nodes -key ca/ca.key -sha256 -days 3650 \
-subj "/CN=My Lab Root CA" -out ca/ca.crt
  1. 服务端证书
1
2
3
4
5
6
7
8
9
10
# Harbor 自己的私钥
openssl genrsa -out server/harbor.key 4096

# 生成 CSR(申请书,注明我要 harbor.lab.local 这个域名)
openssl req -new -key harbor.key -subj "/CN=harbor.lab.local" -out server/harbor.csr

# 用 CA 来签这份申请——注意 SAN,这是最大的坑
openssl x509 -req -in harbor.csr -CA ca/ca.crt -CAkey ca/ca.key -CAcreateserial \
-out server/harbor.crt -days 825 -sha256 \
-extfile <(printf "subjectAltName=DNS:harbor.lab.local,IP:192.168.10.96")

3.4 配置安装

  1. 修改配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
hostname: harbor.lab.local

# 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: /opt/softwares/harbor/certs/server/harbor.crt
private_key: /opt/softwares/harbor/certs/server/harbor.key
  1. 安装
1
./install.sh

四、验证

  1. 账号密码
1
2
admin
Harbor12345
  1. 登录
1
docker login harbor.lab.local -u admin -p 'Harbor12345'
  1. 修改 tag
1
docker tag busybox:1.28 harbor.lab.local/library/busybox:1.28
  1. 推送
1
docker push harbor.lab.local/library/busybox:1.28
  1. 拉取
1
docker pull harbor.lab.local/library/busybox:1.28

五、代理缓存

5.1 原理及准备

客户端拉取镜像时,Harbor 没有的话,回去上游拉取,然后缓存。

harbor 需要访问 dockerhub。系统的 export HTTP_PROXY 只影响宿主机 shell,dockerd 的代理只影响 dockerd 自己 pull——容器里的进程两个都不继承。

1
2
3
4
5
6
7
8
proxy:
http_proxy: http://192.168.10.1:7897
https_proxy: http://192.168.10.1:7897
no_proxy: 127.0.0.1,localhost,core,registry,postgresql,redis,harbor.lab.local
components:
- core
- jobservice
- trivy
1
2
3
./prepare
docker compose down
docker compose up -d

验证

1
docker exec harbor-core env | grep -i proxy

5.2 配置及验证

第一步——建上游 endpoint:Administration → Registries → New Endpoint

  • Provider 选 Docker Hub
  • URL 填 https://hub.docker.com(选了 Docker Hub provider 它会自动处理)
  • 强烈建议填上你的 Docker Hub 账号密码。原因:Docker Hub 对匿名 IP 有拉取限速,填账号能提高额度。而且代理缓存只在第一次拉时占用一次上游配额,团队里再多人拉同一个镜像都走本地缓存——这本身就是省配额的一大好处。

第二步——建代理项目:Projects → New Project

  • 勾选 Proxy Cache,关联刚才那个 endpoint
  • 项目名起个好记的,比如 dockerhub
  • 记住:代理项目是只读的,只能 pull 不能 push

第三步——客户端改镜像名来拉

原来的写法换成带 Harbor 前缀的:

1
2
3
4
5
# 官方镜像(注意!Docker Hub 官方镜像要带 library/ 前缀)
docker pull harbor.lab.local/dockerhub/library/nginx:latest

# 别人的镜像(用户名/镜像名)就不用 library/
docker pull harbor.lab.local/dockerhub/bitnami/redis:latest

那个 library/ 是最容易漏的坑——docker pull nginx 实际等于 docker.io/library/nginx,这个 library/ 在走代理时必须显式写出来,否则会找不到。

第一次拉会慢(Harbor 在背后去上游取),之后同一个镜像就是本地缓存命中,飞快。这就是你说的懒加载。