私有镜像仓库Harbor

私有镜像仓库Harbor

Harbor 是一个开源的企业级容器镜像仓库,可以帮助用户管理和存储 Docker 镜像。它提供了一整套功能,包括用户权限管理、镜像复制、安全扫描、日志审计等,使得在企业内部搭建私有的 Docker 镜像仓库变得非常容易。

一些 Harbor 的特性包括:

  1. 企业级权限管理:可以基于角色进行用户和团队的权限管理,确保镜像的访问和操作受到控制。

  2. 镜像复制和同步:可以将镜像从一个 Harbor 实例复制到另一个,以实现镜像的备份和灾难恢复,或者用于不同环境的部署。

  3. 安全扫描:可以对上传到 Harbor 的镜像进行漏洞扫描,以确保镜像的安全性。

  4. 策略和审计:可以定义策略来规范镜像的上传和使用,同时提供审计日志以跟踪镜像的操作记录。

  5. LDAP/AD 集成:可以与企业的 LDAP 或者 Active Directory 集成,以便于用户身份验证和权限管理。

  6. 多租户支持:可以为不同的团队或项目创建独立的镜像仓库,并对其进行管理。

  7. 灵活的存储后端支持:支持多种存储后端,包括本地存储、NFS、S3、Swift、Azure Blob 等,可以根据需求选择最适合的存储方式。

部署 Harbor 非常简单,可以使用 Docker Compose 或者 Helm Chart 在 Kubernetes 中进行部署。一旦部署完成,就可以开始使用 Harbor 来管理和存储 Docker 镜像了。

参数 配置
主机名 harbor
IP地址 192.168.132.168/24
内存 4Gib
处理器 2vCPU
磁盘空间 4Gib

安装流程:

1、生成证书

修改主机名,创建证书生成的目录,并切换到目录内

[root@localhost ~]# hostnamectl set-hostname harbor && bash
[root@harbor ~]# mkdir -p /data/ssl
[root@harbor ~]# cd /data/ssl/
[root@harbor ssl]# 

生成3072位的CA私钥ca.key

[root@harbor ssl]# openssl genrsa -out ca.key 3072
Generating RSA private key, 3072 bit long modulus
...........++
..............++
e is 65537 (0x10001)

通过CA私钥生成有效期为10年的数字证书ca.pem

[root@harbor ssl]# openssl req -new -x509 -days 3650 -key ca.key -out ca.pem
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:GZ
Locality Name (eg, city) [Default City]:GZ
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:
Email Address []:
参数 解析
openssl req OpenSSL 命令行工具用于处理证书请求的命令
-new OpenSSL 创建一个新的证书请求
-x509 OpenSSL 直接生成一个自签名的 X.509 证书,而不是一个证书请求
-days 3650 指定证书的有效期,这里设置为 3650 天(10 年)
-key ca.key 指定用于生成证书的私钥文件
-out ca.pem 指定输出证书的路径和文件名

为仓库生成私钥文件harbor.key

[root@harbor ssl]# openssl genrsa -out harbor.key 3072
Generating RSA private key, 3072 bit long modulus
.................................++
..........................................++
e is 65537 (0x10001)

使用私钥生成私有仓库的证书请求

[root@harbor ssl]# openssl req -new -key harbor.key -out harbor.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN       
State or Province Name (full name) []:GZ
Locality Name (eg, city) [Default City]:GZ
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:harbor
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:Caijxlinux
An optional company name []:
参数 解释
Country Name (2 letter code) [XX] 国家代码,若没有特殊要求,可以直接回车键跳过
State or Province Name (full name) [] 州或省名,若没有特殊要求,可以直接回车键跳过
Locality Name (eg, city) [Default City] 城市名,若没有特殊要求,可以直接回车键跳过
Organization Name (eg, company) [Default Company Ltd] 组织名,若没有特殊要求,可以直接回车键跳过
Organizational Unit Name (eg, section) [] 组织单位名,可以留空
Common Name (eg, your name or your server's hostname) [] 通用名称,通常是服务器的域名或者主机名。输入 "harbor",表示这个证书与主机名 "harbor" 相关联
Email Address [] 电子邮件地址
A challenge password [] 挑战密码(可选项),可以输入一个密码来保护证书请求,但通常在自签名证书中不使用挑战密码
An optional company name [] 可选的公司名,若没有特殊要求,可以直接回车键跳过

为私有仓库签发证书

[root@harbor ssl]# openssl x509 -req -in harbor.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out harbor.pem -days 3650
Signature ok
subject=/C=CN/ST=GZ/L=GZ/O=Default Company Ltd/CN=harbor
Getting CA Private Key

查看生成的harbor.pem证书内容

[root@harbor ssl]# openssl x509 -in harbor.pem -text -noout
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            b2:3c:b9:07:a8:fa:c8:b3
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=CN, ST=GZ, L=GZ, O=Default Company Ltd
        Validity
            Not Before: Apr 30 16:02:31 2024 GMT
            Not After : Apr 28 16:02:31 2034 GMT
        Subject: C=CN, ST=GZ, L=GZ, O=Default Company Ltd, CN=harbor
...省略部分输出...
2、基础环境配置

关闭防火墙并禁止开机自启

[root@harbor ~]# systemctl stop firewalld && systemctl disable firewalld
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.

安装iptables服务,清空规则,确保服务无启动

[root@harbor ~]# yum -y install iptables
[root@harbor ~]# iptables -F
[root@harbor ~]# service iptables stop
Redirecting to /bin/systemctl stop iptables.service
Failed to stop iptables.service: Unit iptables.service not loaded.

关闭selinux,写入配置文件后需要重启系统

[root@harbor ~]# setenforce 0
[root@harbor ~]# getenforce 
Permissive
[root@harbor ~]# sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config 
[root@harbor ~]# cat /etc/selinux/config | grep 'SELINUX='
# SELINUX= can take one of these three values:
SELINUX=disabled

启用时间同步,并编写定时任务

[root@harbor ~]# yum -y install ntp ntpdate
[root@harbor ~]# ntpdate cn.pool.ntp.org
 1 May 03:27:09 ntpdate[21053]: adjust time server 139.199.214.202 offset 0.007565 sec
[root@harbor ~]# crontab -e
no crontab for root - using an empty one
crontab: installing new crontab
[root@harbor ~]# crontab -l
* */1 * * * /use/sbin/ntpdate cn.pool.ntp.org

重启crond服务使配置生效

[root@harbor ~]# systemctl restart crond

修改mastert-docker主机和harbor主机的hosts文件,添加域名解析

[root@harbor ~]# vim /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.132.167 docker-master
192.168.132.168 harbor
[root@docker-master ~]# vim /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.132.167 docker-master
192.168.132.168 harbor

安装基础软件包

[root@harbor ~]# yum install -y wget net-tools nfs-utils lrzsz gcc gcc-c++ make cmake libxml2-devel openssl-devel curl curl-devel unzip sudo ntp libaio-devel wget vim ncurses-devel autoconf automake zlib-devel python-devel epel-release openssh-server socat ipvsadm conntrack yum-utils device-mapper-persistent-data lvm2

配置docker-ce的国内阿里云仓库源

[root@harbor ~]# yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

安装docker-ce

[root@harbor ~]# yum install docker-ce -y

启动docker服务并查看服务运行状态

[root@harbor ~]# systemctl start docker && systemctl enable docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
[root@harbor ~]# systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
   Active: active (running) since Wed 2024-05-01 03:39:38 EDT; 4s ago
...省略部分输出...

查看docker版本信息

[root@harbor ~]# docker version
Client: Docker Engine - Community
 Version:           26.1.1
 API version:       1.45
 Go version:        go1.21.9
...省略部分输出...

开启包转发功能和修改内核参数

[root@harbor ~]# modprobe br_netfilter
[root@harbor ~]# cat > /etc/sysctl.d/docker.conf <<EOF
> net.bridge.bridge-nf-call-ip6tables = 1
> net.bridge.bridge-nf-call-iptables = 1
> net.ipv4.ip_forward = 1
> EOF
[root@harbor ~]# sysctl -p /etc/sysctl.d/docker.conf 
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1

添加容器镜像加速器,在docker-master上将之前的配置文件复制到harbor主机,并重启docker服务

[root@docker-master ~]# scp /etc/docker/daemon.json 192.168.132.168:/etc/docker/
The authenticity of host '192.168.132.168 (192.168.132.168)' can't be established.
ECDSA key fingerprint is SHA256:jMMK1eMcQLwI18fQnKJCvJhqpMKdOWduyjw7qCaE+lE.
ECDSA key fingerprint is MD5:19:46:92:12:ef:16:9b:f4:0c:83:a9:f4:e2:09:7b:d0.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.132.168' (ECDSA) to the list of known hosts.
root@192.168.132.168's password: 
daemon.json                                                                       100%   67    24.2KB/s   00:00  
3、harbor仓库安装

创建harbor安装目录并切换到目录下

[root@harbor ~]# mkdir /data/install -p
[root@harbor ~]# cd /data/install/
[root@harbor install]# 

上传harbor离线包到目录内

[root@harbor install]# rz
[root@harbor install]# ls
harbor-offline-installer-v2.3.0-rc3.tgz

对离线包进行解压

[root@harbor install]# tar zxvf harbor-offline-installer-v2.3.0-rc3.tgz 
harbor/harbor.v2.3.0.tar.gz
harbor/prepare
harbor/LICENSE
harbor/install.sh
harbor/common.sh
harbor/harbor.yml.tmpl

切换到harbor目录下,复制并修改配置文件名称,并对文件内部分内容进行修改

[root@harbor install]# cd harbor
[root@harbor harbor]# cp harbor.yml.tmpl harbor.yml
[root@harbor harbor]# ls
common.sh  harbor.v2.3.0.tar.gz  harbor.yml  harbor.yml.tmpl  install.sh  LICENSE  prepare
[root@harbor harbor]# vim harbor.yml
#修改 hostname,跟上面签发的证书域名保持一致
hostname: harbor
#协议用 https
certificate: /data/ssl/harbor.pem
private_key: /data/ssl/harbor.key

上传docker-compose软件包到harbor机器随意目录内,并移动软件到/usr/bin目录下修改软件名称和添加执行权限

注: docker-compose 项目是 Docker 官方的开源项目,负责实现对 Docker 容器集群的快速编排。Docker-Compose 的工程配置文件默认为 docker-compose.yml,Docker-Compose 运行目录下的必要有一个docker-compose.yml。docker-compose 可以管理多个 docker 实例。

[root@harbor harbor]# rz
[root@harbor harbor]# ls
common.sh                       harbor.v2.3.0.tar.gz  harbor.yml.tmpl  LICENSE
docker-compose-Linux-x86_64.64  harbor.yml            install.sh       prepare
[root@harbor harbor]# mv docker-compose-Linux-x86_64.64 /usr/bin/docker-compose
[root@harbor harbor]# chmod +x /usr/bin/docker-compose 

上传harbor对应的容器镜像包到harbor机器内,对镜像进行上传

[root@harbor ~]# rz
[root@harbor ~]# ls
anaconda-ks.cfg  docker-harbor-2-3-0.tar.gz
[root@harbor ~]# docker load -i docker-harbor-2-3-0.tar.gz 
7b63ae3694f2: Loading layer  36.92MB/36.92MB
0532e71b3bd4: Loading layer  19.97kB/19.97kB
Loaded image: goharbor/harbor-log:v2.3.0
65081183b9d5: Loading layer  8.112MB/8.112MB
4f1c9ff2daf9: Loading layer  11.64MB/11.64MB
15070dd6843f: Loading layer  1.688MB/1.688MB
Loaded image: goharbor/harbor-portal:v2.3.0
230bb4d21843: Loading layer  9.914MB/9.914MB
3b267db69816: Loading layer  17.67MB/17.67MB
48f062b756ef: Loading layer  4.608kB/4.608kB
83cea239dd18: Loading layer  18.46MB/18.46MB
Loaded image: goharbor/harbor-exporter:v2.3.0
...省略部分输出...

切换到/data/install/harbor目录内,执行安装脚本

[root@harbor ~]# cd /data/install/harbor
[root@harbor harbor]# ./install.sh 
[Step 0]: checking if docker is installed ...
...省略部分输出...
Creating network "harbor_harbor" with the default driver
Creating harbor-log ... done
Creating registryctl   ... done
Creating redis         ... done
Creating registry      ... done
Creating harbor-db     ... done
Creating harbor-portal ... done
Creating harbor-core   ... done
Creating harbor-jobservice ... done
Creating nginx             ... done
✔ ----Harbor has been installed and started successfully.----

在本地服务器内访问harbor仓库,修改添加域名解析,如Windows系统,需要修改hosts文件

拓展:停止/启动harbor仓库

切换到/data/install/harbor目录内,停止docker-compose编排运行的容器

[root@harbor harbor]# cd /data/install/harbor
[root@harbor harbor]# docker-compose stop

切换到/data/install/harbor目录内,启动docker-compose编排运行的容器

[root@harbor harbor]# cd /data/install/harbor
[root@harbor harbor]# docker-compose start

火狐浏览器输入https://harbor进行访问(需要确保域名和IP地址对应正确)

harbor登录界面

仓库的默认账户和密码为admin和Harbor12345

harbor账号密码

library是一个公开的镜像仓库,所有的基础镜像都会存放在里面。

新建一个test项目,访问级别设置为公开,存储容器设置为-1,代表不进行容量限制。

新建项目

在docker-master主机添加docker客户端信任的不安全镜像仓库地址列表,内网访问 harbor 时,使用http协议,IP 地址为 192.168.40.181 和主机名为 harbor 的镜像仓库

[root@docker-master ~]# vim /etc/docker/daemon.json 
{
  "registry-mirrors": ["https://wr3obfzf.mirror.aliyuncs.com"],
  "insecure-registries": ["192.168.132.168","harbor"]
}

重启docker服务,并检查服务运行状态

[root@docker-master ~]# systemctl daemon-reload && systemctl restart docker
[root@docker-master ~]# systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
   Active: active (running) since Wed 2024-05-01 10:49:14 EDT; 4s ago
     Docs: https://docs.docker.com
 Main PID: 22992 (dockerd)
    Tasks: 16
   Memory: 34.7M
   CGroup: /system.slice/docker.service
           └─22992 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
...省略部分输出...

登录harbor

[root@docker-master ~]# docker login 192.168.132.168
Username: admin
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

将centos-repo镜像修改标签,并推送到harbor仓库内

[root@docker-master ~]# docker tag centos-repo:latest 192.168.132.168/test/centos:v1
[root@docker-master ~]# docker push 192.168.132.168/test/centos:v1
The push refers to repository [192.168.132.168/test/centos]
96c615ffd30c: Pushed 
b4bc3775ac78: Pushed 
f3e5301422c6: Pushed 
74ddd0ec08fa: Pushed 
v1: digest: sha256:8e5a011af2073fd2afee3f4767153a5d9035c9216fcc2bddea1fb80d4886b15e size: 1152

查看harbor仓库内是否已经存储了刚才上传的镜像

上传镜像

本地删除centos-repo镜像

[root@docker-master ~]# docker rmi -f 192.168.132.168/test/centos:v1 
Untagged: 192.168.132.168/test/centos:v1
Untagged: 192.168.132.168/test/centos@sha256:8e5a011af2073fd2afee3f4767153a5d9035c9216fcc2bddea1fb80d4886b15e
[root@docker-master ~]# docker images | grep 192
[root@docker-master ~]# 

尝试在仓库进行拉取,测试私有仓库上传下载功能是否完整

[root@docker-master ~]# docker pull 192.168.132.168/test/centos:v1
v1: Pulling from test/centos
Digest: sha256:8e5a011af2073fd2afee3f4767153a5d9035c9216fcc2bddea1fb80d4886b15e
Status: Downloaded newer image for 192.168.132.168/test/centos:v1
192.168.132.168/test/centos:v1
[root@docker-master ~]# docker images | grep 192
192.168.132.168/test/centos   v1        6e0ddaa83100   7 days ago    232MB