镜像私服Harbor 2.0安装-探索工厂模式:如何优化Harbor项目管理与API集成

一、docker-compose

Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。它通过一个配置文件(通常是 docker-compose.yml)来定义应用的服务、网络和卷,并使这些服务能够在单个命令中启动和停止 。

在实际生产环境中,一个应用往往由许多服务构成,而 docker 的最佳实践是一个容器只运行一个进程,因此运行多个微服务就要运行多个容器。多个容器协同工作需要一个有效的工具来管理他们,定义这些容器如何相互关联。compose 应运而生。compose 是用来定义和运行一个或多个容器(通常都是多个)运行和应用的工具。使用 compose 可以简化容器镜像的构建以及容器的运行。compose 使用 YAML 文件来定义多容器之间的关系。一个 docker-compose up 就可以把完整的应用跑起来。 本质上, compose 把 YAML 文件解析成 docker 命令的参数,然后调用相应的 docker 命令行接口,从而将应用以容器化的方式管理起来。它通过解析容器间的依赖关系顺序地启动容器。而容器间的依赖关系由 YAML 文件中的 links 标记指定。

1. 下载 Docker Compose:

sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

这条命令会将 Docker Compose 下载并保存到 /usr/local/bin/docker-compose。
image.png

2.添加执行权限:

sudo chmod +x /usr/local/bin/docker-compose

3.验证安装

docker-compose --version
docker-compose version 1.29.2, build 5becea4c

二、安装harbor 2.0

Harbor是一个开源的企业级Docker Registry,用于存储和分发Docker镜像。它提供了一些额外的安全、身份验证和管理功能,使得在企业环境中更容易管理Docker镜像。您可以通过Harbor来管理镜像的存储、访问控制、安全扫描和复制等功能。

1.下载harbor离线包

可以去https://github.com/goharbor/harbor/releases找到合适的版本下载,或者直接使用这个地址https://github.com/goharbor/harbor/releases/download/v2.0.0/harbor-offline-installer-v2.0.0.tgz 点击它下载下来再传到centos上。
image.png
或者直接在centos上使用命令下

wget -P /usr/local/src/ https://github.com/goharbor/harbor/releases/download/v2.0.0/harbor-offline-installer-v2.0.0.tgz

下载完成后将包上传到服务器的/root/app目录。(你想下载到哪里就放在哪个目录下)

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

[root@localhost app]# ll
总用量 488972
drwxr-xr-x. 2 root root       122 72 11:28 harbor
-rw-r--r--. 1 root root 500705880 624 09:51 harbor-offline-installer-v2.0.0.tgz

2. 根据需求配置 Harbor

解压成功之后进入到harbor目录:

[root@localhost app]# cd harbor
[root@localhost harbor]# cp harbor.yml.tmpl harbor.yml
[root@localhost harbor]# vim harbor.yml

注释:
● hostname写上你要访问的harbor的地址当主机名。
● certificate和private_key是支持HTTPS访问的证书的路径,文件名最好和主机名对应,便于记忆。
● harbor_admin_password是默认的harbor登录的密码
● database-password我猜是默认的harbor数据库密码,默认的是root123,建议改掉。
● data_volume 是数据默认存放目录,即harbor的docker持久化目录默认放在了/data下
或者创建一个

cat > /root/app/harbor/harbor.yml <<EOF
hostname: 192.168.235.130
 
http:
  port: 80
https:
  port: 443
  certificate: /root/app/harbor/certs/192.168.235.130.crt
  private_key: /root/app/harbor/certs/192.168.235.130.key
 
harbor_admin_password: Harbor12345
 
database:
  password: harbor123db
  max_idle_conns: 50
  max_open_conns: 100
 
data_volume: /data
 
clair:
  updaters_interval: 12
trivy:
  ignore_unfixed: false
  skip_update: false
  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.0.0
 
proxy:
  http_proxy:
  https_proxy:
  no_proxy:
  components:
    - core
    - jobservice
    - clair
    - trivy
EOF

3.给harbor创建SSL证书

没有创建证书的话会502错误

  • 安装openssl证书工具
yum install -y openssl
  • 创建证书存放文件夹
[root@localhost harbor]# mkdir certs
[root@localhost harbor]# cd certs/
  • 生成无加密的根证书私钥(注意一定要进到证书目录)
[root@localhost certs]# openssl genrsa -out ca.key 4096
Generating RSA private key, 4096 bit long modulus
..................................................................++
.......................................++
e is 65537 (0x10001)

使用刚才生成的私钥制作自签名证书(将这里的192.168.235.130替换成你的域名即可)

[root@localhost certs]#  openssl req -x509 -new -nodes -sha512 -days 3650 -subj "/C=CN/ST=Beijing/L=Beijing/O=192.168.235.130/OU=192.168.235.130/CN=192.168.235.130" -key ca.key -out ca.crt
[root@localhost certs]# ls
ca.crt  ca.key

生成服务器端自己域名的key(将这里的192.168.235.130替换成你的域名即可)

[root@localhost certs]# openssl genrsa -out 192.168.235.130.key 4096
Generating RSA private key, 4096 bit long modulus
.................................................................................................................................................................................................................++
...............................................................++
e is 65537 (0x10001)

生成服务器端自己域名的CSR签名请求(将这里的192.168.235.130替换成你的域名即可)

openssl req -sha512 -new -subj "/C=CN/ST=Beijing/L=Beijing/O=harbor.hiibm.com/OU=192.168.235.130/CN=192.168.235.130" -key 192.168.235.130.key -out 192.168.235.130.csr
生成一个 openssl 命令需要的外部配置文件 xexternalfile.ext(将这里的192.168.235.130替换成你的域名即可)
cat > xexternalfile.ext <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1=192.168.235.130
EOF

通过外部配置文件 xexternalfile.ext和 csr 生成 crt(将这里的192.168.235.130替换成你的域名即可)

openssl x509 -req -sha512 -days 3650 -extfile xexternalfile.ext -CA ca.crt -CAkey ca.key -CAcreateserial -in 192.168.235.130.csr -out 192.168.235.130.crt

将服务端的 crt 转换成客户端用的 cert(将这里的192.168.235.130替换成你的域名即可)

openssl x509 -inform PEM -in 192.168.235.130.crt -out 192.168.235.130.cert

image.png

4.预编译harbor

cd /root/app/harbor
./prepare

5. 安装并启动 Harbor (必须到你安装的目录)

cd /root/app/harbor
./install.sh

直到看到[✔ ----Harbor has been installed and started successfully.----]才说明harbor安装成功了。
image.png
6.查看docker进程,看harbor是否安装成功

docker ps

image.png
看到一堆包含harbor的docker ps进程
-至此,harbor2.0就安装完成了。

三、登录harbor的web页面

**1. 打开浏览器,访问 http://,使用配置文件中设置的管理员账户(默认用户名为 admin,密码为 Harbor12345)登录到 Harbor 的 Web 界面。 **
image.png
image.png
至此,harbor就彻底安装完成了。

四、harbor的启动和停止

cd /root/app/harbor
 
#停止harbor
docker-compose -f docker-compose.yml down
 
#启动harbor
docker-compose -f docker-compose.yml up -d

五、harbor的使用

  1. 登录Harbor管理界面后,您可以创建项目(Project),用于组织和管理Docker镜像。
  2. 设置项目的访问权限和成员,可以控制谁可以查看、上传和管理镜像
# 登录 用户名密码 admin/Harbor12345
docker login -u admin -p Harbor12345 192.168.235.130  
# 给本地镜像打tag,命令格式如下
docker tag [ImageId] [harbor域名]/[项目名]/[REPOSITORY]:[TAG]
# 上传镜像
docker push [harbor域名]/[项目名]/[REPOSITORY]:[TAG]
eg: docker push 192.168.235.130/wise2c/wisebuild-frontend:harbor-db-v2.0.0
docker push 192.168.235.130/wise2c/wisebuild-frontend:clair-adapter-photon-v2.0.0
docker push 192.168.235.130/wise2c/wisebuild-frontend:clair-photon-v2.0.0
docker push 192.168.235.130/wise2c/wisebuild-frontend:notary-server-photon-v2.0.0
docker push 192.168.235.130/wise2c/wisebuild-frontend:notary-signer-photon-v2.0.0
docker push 192.168.235.130/wise2c/wisebuild-frontend:harbor-registryctl-v2.0.0
docker push 192.168.235.130/wise2c/wisebuild-frontend:registry-photon-v2.0.0
docker push 192.168.235.130/wise2c/wisebuild-frontend:nginx-photon-v2.0.0
docker push 192.168.235.130/wise2c/wisebuild-frontend:harbor-log-v2.0.0
docker push 192.168.235.130/wise2c/wisebuild-frontend:harbor-jobservice-v2.0.0
docker push 192.168.235.130/wise2c/wisebuild-frontend:harbor-core-v2.0.0
docker push 192.168.235.130/wise2c/wisebuild-frontend:harbor-portal-v2.0.0
docker push 192.168.235.130/wise2c/wisebuild-frontend:harbor-db-v2.0.0
docker push 192.168.235.130/wise2c/wisebuild-frontend:prepare-v2.0.0

查看一下 推送成功
image.png
点击复制图标 复制拉取命令

 docker pull 192.168.235.130/wise2c/wisebuild-frontend@sha256:485c21b2cfb96d0213ff1f9a99fe751179078290c6709d247a6e4abf0781fd93

image.png
用户管理:
LDAP集成和OIDC支持:可以集成LDAP或OIDC,管理和认证用户身份。
角色和权限管理:管理用户的角色和权限,以控制其对Harbor功能和资源的访问权限。
仓库管理:
项目和命名空间:创建和管理项目,将镜像组织到命名空间中,便于管理和访问控制。
镜像版本管理:管理镜像的不同版本和标签,支持版本控制和历史记录。
镜像复制:
复制策略:配置镜像复制策略,将镜像同步复制到多个Harbor实例或外部Registry,以提高可用性和冗余性。
标签管理:
标签策略:定义标签策略,管理和限制镜像标签的使用,以维护镜像的一致性和安全性。
项目定额:
资源配额:为每个项目设置资源配额,限制项目可以使用的存储空间和计算资源,以控制资源的分配和使用。
审查服务:
安全扫描服务:集成安全扫描工具,对上传的镜像进行漏洞扫描,并提供漏洞报告和建议修复措施。
垃圾清理:
镜像清理策略:配置镜像保留策略和垃圾清理任务,定期清理过期和未使用的镜像,以节省存储空间并优化性能。
配置管理:
系统配置:管理Harbor的全局设置,包括网络配置、存储后端、SSL证书、日志配置等,以定制化和优化Harbor的运行环境。

六、 探索工厂模式:如何优化Harbor项目管理与API集成

image.png
image.png
image.png
在这个教程中,我们将演示如何使用Java编写代码来访问Harbor的API,并获取特定项目的详细信息。我们将使用Harbor的REST API和Java的HttpClient库进行示例代码编写。
准备工作

  1. 环境要求:

Java开发环境(JDK 8或更高版本)
Maven或Gradle(用于管理依赖)

  1. Harbor实例:

确保您有一个运行中的Harbor实例,并已知道其地址、用户名和密码。

  1. harbor数据库设计

image.png
工厂模式概述
工厂模式是一种常见的创建型设计模式,旨在封装对象的创建过程,使得客户端无需关心具体对象的实例化细节。通过工厂模式,我们可以集中管理对象的创建逻辑,并通过统一的接口或方法提供对象实例。
例分析:Harbor项目管理与API集成
在我们的实例中,我们使用了工厂模式来优化Harbor项目的管理和API集成。具体实现如下:

步骤1:创建Harbor服务和工厂类

首先,我们需要创建一些Java类来管理与Harbor的交互。

Harbor服务类 HarborService.java
import java.util.Optional;

public class HarborService {

    // 根据ID获取Harbor实例
    public Optional<Harbor> harbor(long id) {
        return repository.findById(id); // 假设repository已定义并实现了findById方法
    }

    // 根据Harbor实例ID和项目ID获取项目详细信息
    public Optional<HarborProject> project(long id, int projectId) {
        Optional<Harbor> harbor = harbor(id);

        if (harbor.isPresent()) {
            HarborClientFactory clientFactory = HarborApplicationFactory.getHarborClientFactory(harbor.get());
            return Optional.ofNullable(clientFactory.project(projectId));
        }
        return Optional.empty();
    }
}

Harbor应用工厂类 HarborApplicationFactory.java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HarborApplicationFactory {

    private static final Logger logger = LoggerFactory.getLogger(HarborApplicationFactory.class);

    // 根据Harbor版本返回对应的HarborClientFactory实例
    public static HarborClientFactory getHarborClientFactory(Harbor harbor) {
        if (harbor.getVersion().contains("v1.7") || harbor.getVersion().contains("v1.10")) {
            return new HarborClientFactory10X(harbor.getAddress(), harbor.getUsername(), harbor.getPassword());
        }
        if (harbor.getVersion().contains("v2.0") || harbor.getVersion().contains("v2.10")) {
            return new HarborClientFactory20X(harbor.getAddress(), harbor.getUsername(), harbor.getPassword());
        }
        throw new BizRuntimeException(String.format("当前Harbor版本[%s]不支持", harbor.getVersion()));
    }
}

步骤2:Harbor客户端工厂和API请求类

接下来,我们将创建Harbor客户端工厂和API请求类,用于实际调用Harbor的REST API。

Harbor客户端工厂类 HarborClientFactory.java
public abstract class HarborClientFactory {

    protected final String address;
    protected final String username;
    protected final String password;

    public HarborClientFactory(String address, String username, String password) {
        this.address = address;
        this.username = username;
        this.password = password;
    }

    // 定义获取项目详情的抽象方法
    public abstract HarborProject project(long proID);
}

Harbor 2.0.x版本客户端工厂类 HarborClientFactory20X.java
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HarborClientFactory20X extends HarborClientFactory {

    private static final Logger LOGGER = LoggerFactory.getLogger(HarborClientFactory20X.class);
    private static final String PROJECT_PATH_DEFAULT = "/api/v2.0/projects";

    public HarborClientFactory20X(String address, String username, String password) {
        super(address, username, password);
    }

    @Override
    public HarborProject project(long proID) {
        TrustSslUtil.initDefaultSsl(); // 忽略SSL验证,仅用于本地测试环境
        HarborProject project = new HarborProject();
        String url = address + PROJECT_PATH_DEFAULT + "/" + proID;

        ResponseEntity<Project> response;
        try {
            RestTemplate restTemplate = new RestTemplate();
            response = restTemplate.getForEntity(url, Project.class);
        } catch (HttpClientErrorException e) {
            if (e.getStatusCode() == HttpStatus.NOT_FOUND) {
                throw new BizRuntimeException(String.format("未找到项目[%d]", proID));
            }
            throw new BizRuntimeException(String.format("获取项目[%d]失败: %s", proID, e.getMessage()));
        }

        // 将API响应映射到HarborProject对象
        Project projectResponse = response.getBody();
        if (projectResponse != null) {
            BeanUtils.copyProperties(projectResponse, project);
            project.setDeleted(projectResponse.getDeleted() != null && projectResponse.getDeleted());
            project.setBublic(projectResponse.getMetadata().isPublicX());
        }

        return project;
    }
}

应用工厂模式的好处包括但不限于:

  • 封装对象创建逻辑:将具体的对象实例化过程封装在工厂类中,客户端无需了解具体的实现细节。
  • 简化对象的创建和管理:通过统一的接口或方法,简化了对象的创建和管理过程,提高了代码的灵活性和可维护性。
  • 支持多版本和扩展性:通过工厂模式,可以根据不同的需求或版本,选择合适的对象实例化方式,支持系统的扩展和升级。
public class HarborProject implements Serializable {

    @JsonProperty("project_id")
    private int projectId;

    @JsonProperty("owner_id")
    private int ownerId;

    @JsonProperty("name")
    private String name;

    @JsonProperty("creation_time")
    private Date creationTime;

    @JsonProperty("update_time")
    private Date updateTime;

    @JsonProperty("deleted")
    private int deleted;

    @JsonProperty("owner_name")
    private String ownerName;

    @JsonProperty("public")
    private int bublic;

    @JsonProperty("current_user_role_id")
    private int currentUserRoleId;

    @JsonProperty("repo_count")
    private int repoCount;

    @JsonProperty("metadata")
    private HarborAuthority metadata;

    private Long tenantId;

    private String tenantName;
    
  }

步骤3:HarBorControlle
@RestController
@RequestMapping("/api/harbors")
public class HarborController {

    private static final Logger logger = LoggerFactory.getLogger(HarborController.class);

    private final HarborService harborService;

   @Autowired
    public HarborController(HarborService harborService) {
        this.harborService = harborService;
    }
    
   @GetMapping("/{id}/projects/{projectId}")
    @ApiOperation(value = "查询Harbor实例下的项目", tags = "Harbor")
    public Serializable getHarborProject(@PathVariable("id") long id, @PathVariable("projectId") int projectId) {
        Optional<HarborProject> project = harborService.project(id, projectId);
        if (!project.isPresent()) {
            return BizErrorType.RESOURCE_NOT_FOUND;
        }
        return project.get();
    }
  }

BizErrorType 错误类型定义

public enum BizErrorType {
  RESOURCE_NOT_FOUND("12000001", "请求资源未找到"),
}

TrustSslUtil 忽略ssl工具类

package com.wise2c.biz.util;

import javax.net.ssl.*;
import java.net.Socket;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;

/**
 * 忽略证书验证
 */
public class TrustSslUtil {

    public static void initDefaultSsl() {
        try {
            SSLContext sc = SSLContext.getInstance("SSL");
            HostnameVerifier hv = (urlHostName, session) -> true;
            TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509ExtendedTrustManager() {
                        @Override
                        public void checkClientTrusted(X509Certificate[]
                                                               x509Certificates, String s) {
                        }


                        @Override
                        public void checkServerTrusted(X509Certificate[]
                                                               x509Certificates, String s) {
                        }


                        @Override
                        public X509Certificate[] getAcceptedIssuers() {
                            return null;
                        }


                        @Override
                        public void checkClientTrusted(X509Certificate[]
                                                               x509Certificates, String s, Socket socket) {
                        }


                        @Override
                        public void checkServerTrusted(X509Certificate[]
                                                               x509Certificates, String s, Socket socket) {
                        }


                        @Override
                        public void checkClientTrusted(X509Certificate[]
                                                               x509Certificates, String s, SSLEngine sslEngine) {
                        }


                        @Override
                        public void checkServerTrusted(X509Certificate[]
                                                               x509Certificates, String s, SSLEngine sslEngine) {
                        }
                    }};
            sc.init(null, trustAllCerts, new SecureRandom());


            SSLContext.setDefault(sc);
            HttpsURLConnection.setDefaultHostnameVerifier(hv);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

image.png
image.png

  • 23
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咕噜咕噜wy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值