Skip to content

离线安装Harbor 2.x

前置条件:Docker安装

docker-compose安装

下载

https://github.com/docker/compose/releases

上传改名加权限

bash
mv docker-compose-Linux-x86_64 /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker-compose -v # 测试

下载离线二进制包

Releases · goharbor/harbor :https://github.com/goharbor/harbor/releases

image-20250123145305813

官方的没有ARM镜像,可以使用其他人构建的:

liuli-ke/harbor-arm64: https://github.com/liuli-ke/harbor-arm64

wise2c-devops/build-harbor-aarch64: https://github.com/wise2c-devops/build-harbor-aarch64

解压harbor

bash
tar -xvf harbor-offline-installer-v2.x.x.tgz

修改harbor.yml

进入harbor目录:

bash
cp harbor.yml.tmpl harbor.yml

修改配置文件

yml
# harbor域名,或IP
hostname: harbor.liulike.top

# http不注释,方便没有传证书的服务器走http拉取
http:
  port: 80

https:
  port: 443
  # SSL 证书的路径
  certificate: /data/cert/harbor.liulike.top.crt
  # SSL 密钥的路径
  private_key: /data/cert/harbor.liulike.top.key

# 登录Harbor密码
harbor_admin_password: Harbor12345

database:
  # Harbor数据库密码
  password: root123
  max_idle_conns: 100
  max_open_conns: 900
  conn_max_lifetime: 5m
  conn_max_idle_time: 0

# 数据目录路径
data_volume: /data

log:
  level: info
  local:
    rotate_count: 50
    rotate_size: 200M
    # 日志目录路径
    location: /var/log/harbor

配置https

注意此板块下的 harbor.liulike.topyourdomain.com 请以实际为主,这里都是记录,部分没有调整

使用openssl生成

此步操作要用到openssl,没有需要安装

生成证书颁发机构 证书

1、生成CA证书私钥

bash
openssl genrsa -out ca.key 4096

2、生成 CA 证书

bash
# 注意修改 yourdomain.com 有域名用域名,没有域名用IP

openssl req -x509 -new -nodes -sha512 -days 3650 \
 -subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=yourdomain.com" \
 -key ca.key \
 -out ca.crt

问题:

  1. Can't load /root/.rnd into RNG

    bash
    # 解决办法:
    cd /root
    openssl rand -writerand .rnd

    重新执行即可

生成服务器证书

1、生成私钥

bash
# 注意修改 yourdomain.com 有域名用域名,没有域名用IP
openssl genrsa -out yourdomain.com.key 4096

2、生成证书签名请求 (CSR)

bash
# 注意修改 yourdomain.com 有域名用域名,没有域名用IP
openssl req -sha512 -new \
    -subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=yourdomain.com" \
    -key yourdomain.com.key \
    -out yourdomain.com.csr

3、生成 x509 v3 扩展文件

bash
# 注意修改 yourdomain.com 有域名用域名,没有域名用IP
cat > v3.ext <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1=yourdomain.com
DNS.2=yourdomain
DNS.3=hostname
EOF

问题:

  1. 域名方式

    DNS.x可以继续加授信域名

  2. IP方式

    bash
    cat > v3.ext <<-EOF
    authorityKeyIdentifier=keyid,issuer
    basicConstraints=CA:FALSE
    keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
    extendedKeyUsage = serverAuth
    subjectAltName = IP:xxx.xxx.xxx.xxx
    EOF

4、使用 v3.ext 文件,为 Harbor 主机生成证书

bash
# 注意修改 yourdomain.com 有域名用域名,没有域名用IP
openssl x509 -req -sha512 -days 3650 \
    -extfile v3.ext \
    -CA ca.crt -CAkey ca.key -CAcreateserial \
    -in yourdomain.com.csr \
    -out yourdomain.com.crt

生成客户端证书

转换 yourdomain.com.crtyourdomain.com.cert, 供 Docker 使用。

Docker 守护程序解释 .crt 文件 作为 CA 证书和 .cert 文件作为客户端证书

bash
openssl x509 -inform PEM -in yourdomain.com.crt -out yourdomain.com.cert

脚本

bash
#!/bin/bash
domain='harbor.liulike.top'
hostname='xxx.xxx.xxx.xxx'

echo "========== 生成CA证书 =========="

echo "生成CA证书私钥"
openssl genrsa -out ca.key 4096

echo "生成 CA 证书"
openssl req -x509 -new -nodes -sha512 -days 3650 \
 -subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=${domain}" \
 -key ca.key \
 -out ca.crt


echo "========== 生成服务器证书 =========="
echo "生成私钥"
openssl genrsa -out ${domain}.key 4096

echo "生成证书签名请求 (CSR)"
openssl req -sha512 -new \
    -subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=${domain}" \
    -key ${domain}.key \
    -out ${domain}.csr

echo "生成 x509 v3 扩展文件"
cat > v3.ext <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1=${domain}
DNS.2=${hostname}
EOF


echo '使用 `v3.ext` 文件,为 Harbor 主机生成证书'
openssl x509 -req -sha512 -days 3650 \
    -extfile v3.ext \
    -CA ca.crt -CAkey ca.key -CAcreateserial \
    -in ${domain}.csr \
    -out ${domain}.crt


echo '生成cert客户端证书'
openssl x509 -inform PEM -in ${domain}.crt -out ${domain}.cert

echo '更新docker客户端证书目录'
rm -rf /etc/docker/certs.d/${domain}/*
cp {ca.crt,${domain}.cert,${domain}.key} /etc/docker/certs.d/${domain}/
ls /etc/docker/certs.d/${domain}/

使用CFSSL生成证书

cfssl安装这里不展开,这里使用cfssl1.6.5

ca-config.json

用于定义CA的签名策略,包括证书的过期时间等

json
{  
  "signing": {  
    "default": {  
      "expiry": "87600h",
      "ca_constraint": {  
        "is_ca": true,  
        "max_path_len": 0
      }  
    },  
    "profiles": {  
      "server": {  
        "expiry": "43800h",
        "usages": [  
          "signing",  
          "key encipherment",  
          "server auth",  
          "client auth"  
        ]  
      }  
    }  
  }  
}

ca-csr.json

bash
{
  "CN": "Liulike CA",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "L": "Liulike",
      "ST": "Liulike",
      "O": "Liulike",
      "OU": "Liulike TEST"
    }
  ]
}

生成CA证书和私钥

bash
echo "生成CA证书和私钥"
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -

server-csr.json

服务器证书签名请求(CSR)的JSON配置文件

json
{
  "CN": "harbor.liulike.top",
  "hosts": [
    "harbor.liulike.top",
    "xxx.xxx.xxx.xxx"
  ],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "L": "Liulike",
      "ST": "Liulike",
      "O": "Liulike",
      "OU": "Liulike TEST"
    }
  ]
}

所有的证书都可以写在hosts列表里

生成服务器私钥和CSR

bash
echo "签署服务器证书"
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server server-csr.json | cfssljson -bare server

调整证书的名称

bash
mv ca.pem ca.crt
mv ca-key.pem ca.key
cp server.pem harbor.liulike.top.cert   # 复制用于客户端证书
mv server.pem harbor.liulike.top.crt
mv server-key.pem harbor.liulike.top.key

向 Harbor 和 Docker 提供证书

生成后 ca.crt, yourdomain.com.crtyourdomain.com.key,必须将它们提供给 Harbor 和 Docker,并配置或重新配置 Harbor 。

1、将服务器证书和密钥复制到 Harbor 主机上的证书文件夹中。

bash
cp yourdomain.com.crt /data/cert/
cp yourdomain.com.key /data/cert/

2、将服务器证书、密钥和 CA 文件复制到 Harbor 主机上的 Docker 证书文件夹中。必须先创建相应的文件夹。

sh
cp yourdomain.com.cert /etc/docker/certs.d/yourdomain.com/
cp yourdomain.com.key /etc/docker/certs.d/yourdomain.com/
cp ca.crt /etc/docker/certs.d/yourdomain.com/

部署或重新配置Harbor

未部署 Harbor

如果尚未部署 Harbor,请参阅 修改harbor.yml 修改 harbor.yml 中的属性: hostnamehttps 数据目录、密码等。

运行脚本以启用 HTTPS

bash
./prepare
./install.sh

已部署 Harbor

如果 Harbor 正在运行,请停止并删除现有实例

镜像数据保留在文件系统中,因此不会丢失任何数据

bash
docker-compose down -v

更新配置

bash
./prepare

启动/重新启动Harbor

bash
docker-compose up -d

docker-compose命令:

bash
docker-compose ps		
docker-compose up -d 	# 后台启动,如果容器不存在根据镜像自动创建
docker-compose down -v	# 停止容器并删除容器
docker-compose start	# 启动容器,如果容器不存在就无法启动,不会自动创建镜像
docker-compose stop		# 停止容器
docker-compose logs		# 查看日志(harbor日志默认存放地址/ver/logs/harbor)

1、使用IP或域名访问WEB、登录

2、docker登录

bash
docker login harbor.liulike.top
docker login xxx.xxx.xxx.xxx

输入账号密码

推送镜像

创建项目 ——> xxx

1、制作镜像标签

bash
docker tag 镜像名:标签 IP/项目名/镜像名:标签

推送镜像

bash
docker push IP/项目名/镜像名:标签

如果在其他地方连接说不安全,可以将ca证书安装即可,

如果使用证书颁发者的中间证书,请将中间证书与您自己的证书合并以创建证书捆绑包。运行以下命令

bash
cat intermediate-certificate.pem >> yourdomain.com.crt

当 Docker 守护程序在某些操作系统上运行时,您可能需要在操作系统级别信任证书。例如,运行以下命令

Ubuntu

bash
cp yourdomain.com.crt /usr/local/share/ca-certificates/yourdomain.com.crt 
update-ca-certificates

Red Hat (CentOS 等)

bash
cp yourdomain.com.crt /etc/pki/ca-trust/source/anchors/yourdomain.com.crt
update-ca-trust

win直接下载ca根证书安装,安装完证书后重启Docker

配置开机启动

bash
vi /etc/systemd/system/harbor.service

添加:

bash
[Unit]
Description=Harbor
After=docker.service systemd-networkd.service systemd-resolved.service
Requires=docker.service
Documentation=http://github.com/vmware/harbor

[Service]
Type=simple
Restart=on-failure
RestartSec=5
ExecStart=/usr/local/bin/docker-compose -f 安装目录/docker-compose.yml up
ExecStop=/usr/local/bin/docker-compose -f 安装目录/docker-compose.yml down

[Install]
WantedBy=multi-user.target

配置权限

chmod 755 harbor.service   # 配置权限

systemctl daemon-reload    # 重载

systemctl enable harbor    # 开机启动

systemctl status harbor    # 查看状态

配置完成检查发现harbor状态没有,是停止的,但是手动执行docker-compose ps检查发现是正常运行的

使用 systemctl restart harbor 重启一次就好了

问题记录

Creating network "harbor_harbor" with the default driver
ERROR: Failed to Setup IP tables: Unable to enable SKIP DNAT rule:  (iptables failed: iptables --wait -t nat -I DOCKER -i br-cbded1298bf1 -j RETURN: iptables: No chain/target/match by that name.
 (exit status 1))

说明docker网关是关闭的,docker network无法对新的container进行网络配置,重启一下docker就行。

systemctl restart docker

Docker http登录Harbor

新建或修改

bash
vi /etc/docker/daemon.json
json
{
  "insecure-registries":["IP或域名"],
  "live-restore": true
}

Harbor仓库迁移

这里是以http部署的迁移,https的迁移可以参考一下

前置条件:有Docker环境,与原版本建议相差不要太大,最好等于/大于原来的docker版本

安装docker-compose

下载

https://github.com/docker/compose/releases

上传改名加权限

bash

$ mv docker-compose-Linux-x86_64 /usr/local/bin/docker-compose
$ chmod +x /usr/local/bin/docker-compose
$ docker-compose -v # 测试

停止原Harbor仓库

bash
$ systemctl stop harbor # 有配置的话
# 没有的话到 /.../Harbor/harbor目录下执行
$ docker-compose down

Harbor数据迁移

将原来的Harbor数据打包,我是整个目录打包,整个目录结构大致如下

bash
Harbor
├── data    # 数据目录
├── harbor  # harbor离线包解压出来的目录
│   ├── common
│   ├── docker-compose.yml # docker-compose用到的文件
│   ├── harbor.v2.xx.xx.tar.gz # 离线镜像包,docker load使用
│   ├── harbor.yml # harbor的配置文件
│   ├── install.sh # harbor安装脚本【除了第一次后面不要执行,执行会导致原来的数据不可用】
│   └── prepare
├── harbor-offline-installer-v2.xx.xx.tgz
└── logs

导入离线镜像

/.../Harbor/harbor目录下执行

bash
$ docker load -i harbor.v2.xx.xx.tar.gz

调整配置

修改/.../Harbor/harbor目录下的harbor.yml文件

bash
hostname: harbor.liulike.top
data_volume: /data/Harbor/data
log:
    location: /var/log/harbor

hostname:如果原来配置的是IP地址,必须修改,如果是域名,根据需要看是否调整解析/调整hosts等

data_volume:新的数据目录

https的:除了以上内容外,还需要调整证书的路径

修改完毕执行

bash
$ ./prepare

配置开机启动

bash
$ vi /etc/systemd/system/harbor.service

添加:

bash
[Unit]
Description=Harbor
After=docker.service systemd-networkd.service systemd-resolved.service
Requires=docker.service
Documentation=http://github.com/vmware/harbor

[Service]
Type=simple
Restart=on-failure
RestartSec=5
ExecStart=/usr/local/bin/docker-compose -f /.../Harbor/harbor目录/docker-compose.yml up
ExecStop=/usr/local/bin/docker-compose -f /.../Harbor/harbor目录/docker-compose.yml down

[Install]
WantedBy=multi-user.target

配置权限

bash
$ chmod 755 harbor.service   # 配置权限

$ systemctl daemon-reload    # 重载

$ systemctl enable harbor    # 开机启动

$ systemctl status harbor    # 查看状态

$ systemctl start harbor    # 启动

$ systemctl stop harbor    # 停止

配置使用Harbor私有仓库

Containerd

编辑文件 /etc/containerd/config.toml ,注意缩进

toml
# 定义 plugins 的配置区域
[plugins]
  # 定义 io.containerd.grpc.v1.cri 的插件配置
  [plugins."io.containerd.grpc.v1.cri"]
    # 定义 io.containerd.grpc.v1.cri 插件下的镜像仓库配置
    [plugins."io.containerd.grpc.v1.cri".registry]
      # 定义镜像源的配置
      [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
        # 定义 docker.io 镜像源的配置
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
          # 设置 docker.io 镜像源的端点地址
          endpoint = ["https://registry-1.docker.io"]
        # 定义 harbor.liulike.top 镜像源的配置
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."harbor.liulike.top"]
          # # 设置 harbor.liulike.top 镜像源的端点地址
          endpoint = ["http://harbor.liulike.top"]

      # 定义镜像仓库的配置
      [plugins."io.containerd.grpc.v1.cri".registry.configs]
        # 定义 harbor.liulike.top 镜像仓库的TLS配置
        [plugins."io.containerd.grpc.v1.cri".registry.configs."harbor.liulike.top".tls]
          # 是否跳过证书认证, 配置在建立TLS连接时不验证服务器证书合法性
          insecure_skip_verify = true
        [plugins."io.containerd.grpc.v1.cri".registry.configs."harbor.liulike.top".tls]
          # 是否跳过证书认证, 配置在建立TLS连接时不验证服务器证书合法性
          insecure_skip_verify = false
          # 指定harbor的CA证书
          ca_file = "/etc/containerd/certs.d/harbor.liulike.top/ca.crt"
          # 如果是双向认证,需要添加客户端的公钥和私钥
          # cert_file = "/etc/containerd/certs.d/harbor.liulike.top/client.cert"
          # key_file = "/etc/containerd/certs.d/harbor.liulike.top/client.key"
        # 如果针对某个项目使用,可以在 Harbor 里创建的用户,并授权访问指定项目
        [plugins."io.containerd.grpc.v1.cri".registry.configs."harbor.liulike.top".auth]
          username = "username"
          password = "password"

注意测试

网上存在结构除了上面的还有以下结构,以下结构只截取部分,仅供参考

toml
[plugins]
  [plugins."io.containerd.grpc.v1.cri"]
    # 定义 io.containerd.grpc.v1.cri 插件下的镜像仓库配置
    [plugins."io.containerd.grpc.v1.cri".registry]
      [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
        # 定义镜像仓库的配置
        [plugins."io.containerd.grpc.v1.cri".registry.configs]
          # 定义 harbor.liulike.top 镜像源的配置
          [plugins."io.containerd.grpc.v1.cri".registry.mirrors."harbor.liulike.top"]
            endpoint = ["http://harbor.liulike.top"]
bash
$ systemctl daemon-reload
$ systemctl restart containerd

Docker

编辑/新增文件 /etc/docker/daemon.json ,注意缩进

json
{
  "insecure-registries": ["harbor.liulike.top"]
}

配置证书走https?

/etc/docker/certs.d 新建仓库地址的文件夹名,如 harbor.liulike.top 里面放 ca.crtharbor.liulike.top.certharbor.liulike.top.key

注意,对于Harbor cert 是客户端证书, crt 是服务端证书

bash
$ systemctl restart docker

Harbor2小版本升级

注意:条件允许请一定一定一定对旧版本信息进行备份

这里测试的时候这几个路径为:/data/Harbor/

备份旧数据

bash
# 停止Harbor
$ cd data/Harbor
$ docker-compose down
# 备份原目录
$ mv /data/Harbor /data/Harbor2.xx.xx

解压新的离线包

bash
$ tar -xf harbor-offline-installer-v2.yy.yy.tgz
$ mv /data/harbor /data/Harbor

导入版本的镜像

bash
# 清理旧版本镜像
$ docker rmi `docker images | grep goharbor | awk '{print $3}'`
# 导入新镜像
$ docker load -i /data/Harbor/harbor.v2.yy.yy.tar.gz

配置文件迁移

bash
$ cp -a /data/Harbor2.xx.xx/harbor.yml /data/Harbor/
$ docker run -it --rm -v /data/Harbor/harbor.yml:/hostfs/harbor.yml goharbor/prepare:v2.yy.yy migrate -i harbor.yml

复制或移动数据目录到新版本目录下

bash
$ cp -a /data/Harbor2.xx.xx/data /data/Harbor/   # 复制
# mv /data/Harbor2.xx.xx/data /data/Harbor/      # 移动

启动新版本

注意: 数据库的模式升级和数据迁移在 Harbor 启动时由 core 执行。如果迁移失败,请检查 core 日志以进行调试

bash
$ cd /data/Harbor
$ ./install.sh                      # 不包含 Trivy 的默认安装
$ ./install.sh --with-trivy         # 包含 Trivy 的安装

版本回滚

由于升级前备份了对应的数据、配置等,只需要将新的去掉,将旧版本拉起来即可

bash
$ rm -rf /data/Harbor/
# 清理旧版本镜像
$ docker rmi `docker images | grep goharbor | awk '{print $3}'`
# mv /data/Harbor2.xx.xx /data/Harbor
# 导入新镜像
$ docker load -i /data/Harbor/harbor.v2.xx.xx.tar.gz
$ cd /data/Harbor
$ docker-compose up -d

Harbor安装配置helm仓库

harbor启用helm chart仓库(harbor 2.8之前)

默认新版 harbor 不会启用 chart repository service,如果启用,安装命令要添加一个参数 --with-chartmuseum

bash
$ ./install.sh --with-chartmuseum

如果是安装后后修改,可以使用

bash
docker-compose down # 或 docker-compose stop
./prepare --with-chartmuseum
docker-compose up -d

启用后Harbor中有独立的Helm Charts页面。Charts支持UI上传、helm push两种上传chart的方式。

Harbor2.8(包括)之后管理Helm Charts

2.8之后harbor弃用了chartmuseum。Harbor中Charts与Image保存在相同目录下,没有单独的页面。

操作实例如下,本文Harbor域名为 harbor.liulike.top, 使用如下方式上传下载Chart:

bash
# 登录helm仓库
root@master1:~/harbor# helm registry login harbor.liulike.top --insecure
Username: admin
Password:
Login Succeeded

# 提前在harbor中创建harbor项目。上传不再支持UI界面,必须使用helm push。需要提前在harbor中创建名为harbor的project
root@master1:~/harbor# helm push harbor-1.15.0.tgz oci://harbor.liulike.top/harbor
Error: failed to do request: Head "https://harbor.liulike.top/v2/harbor/harbor/blobs/sha256:c51d391fc1d26224da59d97cc0428ecc9be64c9ca5ba9381f4e48f696bf41dc5": tls: failed to verify certificate: x509: certificate signed by unknown authority

# 添加--insecure-skip-tls-verify跳过tls证书验证。
root@master1:~/harbor# helm push harbor-1.15.0.tgz oci://harbor.liulike.top/harbor --insecure-skip-tls-verify
Pushed: harbor.liulike.top/harbor/harbor:1.15.0
Digest: sha256:2bb53e13ae59d5478ca90734b2c267096a1919a9a63875e583b87efff76a4532

# 下载。下载命令web界面可以复制
helm pull oci://harbor.liulike.top/harbor/harbor --version 1.15.0