本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 [署名 4.0 国际 (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/deed.zh) 本文作者: 苏洋 创建时间: 2020年05月23日 统计字数: 22208字 阅读时间: 45分钟阅读 本文链接: https://soulteary.com/2020/05/23/use-harbor-to-build-a-private-docker-repository.html ----- # 使用 Harbor 搭建私有 Docker 仓库 最近在尝试跨云服务商做备份,除了应用之外的基础设施也需要再启动一套仓库。正巧赶上 Harbor 发布 2.0,于是就有了这篇文章。 ## 准备工作 我们需要准备应用安装目录,然后从官网仓库获取最近发布的稳定版:[https://github.com/goharbor/harbor](https://github.com/goharbor/harbor): ```bash mkdir /app/docker.soulteary.com cd /app/docker.soulteary.com wget https://github.com/goharbor/harbor/releases/download/v2.0.0/harbor-offline-installer-v2.0.0.tgz ``` ### 校验安装文件 用于生产或开发环境的工具,安全性还是需要一定保障的。最基础的方式就是比对校验文件和我们所下载的文件的校验值是否一致。 #### 使用 MD5 做基础校验 先从官网获取对应版本的 **md5sum** 文件。 ```bash wget https://github.com/goharbor/harbor/releases/download/v2.0.0/md5sum ``` 然后使用 `md5sum -c md5sum` 来查看文件内容是否正确,如果正确,会显示下面的内容。 ```bash harbor-offline-installer-v2.0.0.tgz: OK ``` #### 使用 GnuPG 进一步 验证文件签名 相比较 **md5** 校验值,GnuPG 签名检查更值得信赖。还是需要先获取校验文件: ```bash wget https://github.com/goharbor/harbor/releases/download/v2.0.0/harbor-offline-installer-v2.0.0.tgz.asc ``` 获取完毕后,执行 `md5sum -c md5sum` 来查看文件内容是否正确。 ```bash harbor-offline-installer-v2.0.0.tgz.asc: OK ``` 接着获取签名的公钥: ```bash gpg --keyserver hkps://keyserver.ubuntu.com --receive-keys 644FF454C0B4115C gpg: /root/.gnupg/trustdb.gpg: trustdb created gpg: key 644FF454C0B4115C: public key "Harbor-sign (The key for signing Harbor build) " imported gpg: Total number processed: 1 gpg: imported: 1 ``` 最后使用 `gpg --verify` 对安装文件进行校验即可。 ```bash gpg --verify harbor-offline-installer-v2.0.0.tgz.asc harbor-offline-installer-v2.0.0.tgz gpg: Signature made Mon 11 May 2020 06:49:33 PM CST gpg: using RSA key 644FF454C0B4115C gpg: Good signature from "Harbor-sign (The key for signing Harbor build) " [unknown] gpg: WARNING: This key is not certified with a trusted signature! gpg: There is no indication that the signature belongs to the owner. Primary key fingerprint: 7722 D168 DAEC 4578 06C9 6FF9 644F F454 C0B4 115C ``` ## 准备安装 离线安装包里包含了基本我们所需要的内容,解压缩后的内容如下: ```bash tar xvf 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 ``` ### 编辑配置文件 复制默认模版文件 **harbor.yml.tmpl** 并重命名为 **harbor.yml**,并按照自己需求更新该配置文件。 ```bash cp harbor.yml.tmpl harbor.yml vim harbor.yml ``` 默认配置文件如下: ```yaml # Configuration file of Harbor # The IP address or hostname to access admin UI and registry service. # DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients. hostname: reg.mydomain.com # 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: /your/certificate/path private_key: /your/private/key/path # # Uncomment following will enable tls communication between all harbor components # internal_tls: # # set enabled to true means internal tls is enabled # enabled: true # # put your cert and key files on dir # dir: /etc/harbor/tls/internal # Uncomment external_url if you want to enable external proxy # And when it enabled the hostname will no longer used # external_url: https://reg.mydomain.com:8433 # The initial password of Harbor admin # It only works in first time to install harbor # Remember Change the admin password from UI after launching Harbor. harbor_admin_password: Harbor12345 # Harbor DB configuration database: # The password for the root user of Harbor DB. Change this before any production use. password: root123 # The maximum number of connections in the idle connection pool. If it <=0, no idle connections are retained. max_idle_conns: 50 # The maximum number of open connections to the database. If it <= 0, then there is no limit on the number of open connections. # Note: the default number of connections is 100 for postgres. max_open_conns: 100 # The default data volume data_volume: /data # Harbor Storage settings by default is using /data dir on local filesystem # Uncomment storage_service setting If you want to using external storage # storage_service: # # ca_bundle is the path to the custom root ca certificate, which will be injected into the truststore # # of registry's and chart repository's containers. This is usually needed when the user hosts a internal storage with self signed certificate. # ca_bundle: # # storage backend, default is filesystem, options include filesystem, azure, gcs, s3, swift and oss # # for more info about this configuration please refer https://docs.docker.com/registry/configuration/ # filesystem: # maxthreads: 100 # # set disable to true when you want to disable registry redirect # redirect: # disabled: false # Clair configuration clair: # The interval of clair updaters, the unit is hour, set to 0 to disable the updaters. updaters_interval: 12 # Trivy configuration trivy: # ignoreUnfixed The flag to display only fixed vulnerabilities ignore_unfixed: false # skipUpdate The flag to enable or disable Trivy DB downloads from GitHub # # You might want to enable this flag in test or CI/CD environments to avoid GitHub rate limiting issues. # If the flag is enabled you have to manually download the `trivy.db` file and mount it in the # /home/scanner/.cache/trivy/db/trivy.db path. skip_update: false # # insecure The flag to skip verifying registry certificate insecure: false # github_token The GitHub access token to download Trivy DB # # Trivy DB contains vulnerability information from NVD, Red Hat, and many other upstream vulnerability databases. # It is downloaded by Trivy from the GitHub release page https://github.com/aquasecurity/trivy-db/releases and cached # in the local file system (/home/scanner/.cache/trivy/db/trivy.db). In addition, the database contains the update # timestamp so Trivy can detect whether it should download a newer version from the Internet or use the cached one. # Currently, the database is updated every 12 hours and published as a new release to GitHub. # # Anonymous downloads from GitHub are subject to the limit of 60 requests per hour. Normally such rate limit is enough # for production operations. If, for any reason, it's not enough, you could increase the rate limit to 5000 # requests per hour by specifying the GitHub access token. For more details on GitHub rate limiting please consult # https://developer.github.com/v3/#rate-limiting # # You can create a GitHub token by following the instuctions in # https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line # # github_token: xxx jobservice: # Maximum number of job workers in job service max_job_workers: 10 notification: # Maximum retry count for webhook job webhook_job_max_retry: 10 chart: # Change the value of absolute_url to enabled can enable absolute url in chart absolute_url: disabled # Log configurations log: # options are debug, info, warning, error, fatal level: info # configs for logs in local storage local: # Log files are rotated log_rotate_count times before being removed. If count is 0, old versions are removed rather than rotated. rotate_count: 50 # Log files are rotated only if they grow bigger than log_rotate_size bytes. If size is followed by k, the size is assumed to be in kilobytes. # If the M is used, the size is in megabytes, and if G is used, the size is in gigabytes. So size 100, size 100k, size 100M and size 100G # are all valid. rotate_size: 200M # The directory on your host that store log location: /var/log/harbor # Uncomment following lines to enable external syslog endpoint. # external_endpoint: # # protocol used to transmit log to external endpoint, options is tcp or udp # protocol: tcp # # The host of external endpoint # host: localhost # # Port of external endpoint # port: 5140 #This attribute is for migrator to detect the version of the .cfg file, DO NOT MODIFY! _version: 2.0.0 # Uncomment external_database if using external database. # external_database: # harbor: # host: harbor_db_host # port: harbor_db_port # db_name: harbor_db_name # username: harbor_db_username # password: harbor_db_password # ssl_mode: disable # max_idle_conns: 2 # max_open_conns: 0 # clair: # host: clair_db_host # port: clair_db_port # db_name: clair_db_name # username: clair_db_username # password: clair_db_password # ssl_mode: disable # notary_signer: # host: notary_signer_db_host # port: notary_signer_db_port # db_name: notary_signer_db_name # username: notary_signer_db_username # password: notary_signer_db_password # ssl_mode: disable # notary_server: # host: notary_server_db_host # port: notary_server_db_port # db_name: notary_server_db_name # username: notary_server_db_username # password: notary_server_db_password # ssl_mode: disable # Uncomment external_redis if using external Redis server # external_redis: # host: redis # port: 6379 # password: # # db_index 0 is for core, it's unchangeable # registry_db_index: 1 # jobservice_db_index: 2 # chartmuseum_db_index: 3 # clair_db_index: 4 # trivy_db_index: 5 # idle_timeout_seconds: 30 # Uncomment uaa for trusting the certificate of uaa instance that is hosted via self-signed cert. # uaa: # ca_file: /path/to/ca # Global proxy # Config http proxy for components, e.g. http://my.proxy.com:3128 # Components doesn't need to connect to each others via http proxy. # Remove component from `components` array if want disable proxy # for it. If you want use proxy for replication, MUST enable proxy # for core and jobservice, and set `http_proxy` and `https_proxy`. # Add domain to the `no_proxy` field, when you want disable proxy # for some special registry. proxy: http_proxy: https_proxy: no_proxy: components: - core - jobservice - clair - trivy ``` 一般情况下,我们最少需要配置的内容如下: - **hostname** 需要配置为 **127.0.0.1** 之外的内容,以提供外部访问,本例中我配置为: docker.soulteary.com - **https** 的配置需要同时配置证书,生产环境中,如果使用 SLB 或者使用其他应用统一提供 SSL 接入,则可以删除。 - **harbor\_admin\_password** 默认密码即可,但是初次使用登陆后台后需要修改密码。 - **data\_volume** 根据自己实际情况修改宿主机的文件储存地址。 ### 执行安装 修改完配置之后,使用 `bash install.sh` 进行应用安装。 ```yaml [Step 0]: checking if docker is installed ... Note: docker version: 19.03.9 [Step 1]: checking docker-compose is installed ... Note: docker-compose version: 1.25.3 [Step 2]: loading Harbor images ... dbaf2c918102: Loading layer [==================================================>] 34.5MB/34.5MB 1f3458bb7308: Loading layer [==================================================>] 8.435MB/8.435MB 74e91bd5ca15: Loading layer [==================================================>] 6.317MB/6.317MB 82da861dccd3: Loading layer [==================================================>] 14.61MB/14.61MB 8d62f2bfdf94: Loading layer [==================================================>] 28.25MB/28.25MB 40510e398799: Loading layer [==================================================>] 22.02kB/22.02kB 6941a908d292: Loading layer [==================================================>] 49.17MB/49.17MB Loaded image: goharbor/notary-signer-photon:v2.0.0 bd70463b9e5a: Loading layer [==================================================>] 8.441MB/8.441MB d3927e3c53ea: Loading layer [==================================================>] 3.584kB/3.584kB a3b2acbb8f7d: Loading layer [==================================================>] 3.072kB/3.072kB de14f7f144ce: Loading layer [==================================================>] 9.71MB/9.71MB 94c03f31b276: Loading layer [==================================================>] 10.53MB/10.53MB Loaded image: goharbor/clair-adapter-photon:v2.0.0 935e17d700d1: Loading layer [==================================================>] 8.44MB/8.44MB eef8d67e9248: Loading layer [==================================================>] 42.3MB/42.3MB a181769f3c52: Loading layer [==================================================>] 3.072kB/3.072kB 4b801e4d76d7: Loading layer [==================================================>] 3.584kB/3.584kB 7f7c81a33722: Loading layer [==================================================>] 43.12MB/43.12MB Loaded image: goharbor/chartmuseum-photon:v2.0.0 4076b322e7f5: Loading layer [==================================================>] 49.89MB/49.89MB da16bbe3a170: Loading layer [==================================================>] 3.584kB/3.584kB f8967a1d9155: Loading layer [==================================================>] 3.072kB/3.072kB 6b7eaf984fde: Loading layer [==================================================>] 2.56kB/2.56kB 4406aea83cb2: Loading layer [==================================================>] 3.072kB/3.072kB 78566a971bf2: Loading layer [==================================================>] 3.584kB/3.584kB e4e05e2ffdad: Loading layer [==================================================>] 12.29kB/12.29kB f3bcf1de026d: Loading layer [==================================================>] 5.632kB/5.632kB Loaded image: goharbor/harbor-log:v2.0.0 101133a0a2e6: Loading layer [==================================================>] 8.441MB/8.441MB 40eb3ab360dd: Loading layer [==================================================>] 3.584kB/3.584kB 172ace267ace: Loading layer [==================================================>] 20.94MB/20.94MB cb361129c579: Loading layer [==================================================>] 3.072kB/3.072kB f0221c34f9dc: Loading layer [==================================================>] 8.721MB/8.721MB 1880cedc9407: Loading layer [==================================================>] 30.48MB/30.48MB Loaded image: goharbor/harbor-registryctl:v2.0.0 15f399ca8b42: Loading layer [==================================================>] 8.441MB/8.441MB 182251d62618: Loading layer [==================================================>] 3.584kB/3.584kB c72ce5e8bba9: Loading layer [==================================================>] 3.072kB/3.072kB 6cb620513867: Loading layer [==================================================>] 20.94MB/20.94MB 8f68617c13e6: Loading layer [==================================================>] 21.76MB/21.76MB Loaded image: goharbor/registry-photon:v2.0.0 464d98f962d2: Loading layer [==================================================>] 115.2MB/115.2MB 6f577ce93b49: Loading layer [==================================================>] 12.15MB/12.15MB 468b747374fb: Loading layer [==================================================>] 3.072kB/3.072kB c7d4e40274a2: Loading layer [==================================================>] 49.15kB/49.15kB 349c2528bf8f: Loading layer [==================================================>] 3.584kB/3.584kB 50765adb1994: Loading layer [==================================================>] 13.03MB/13.03MB Loaded image: goharbor/clair-photon:v2.0.0 f3ae9281f64f: Loading layer [==================================================>] 16.04MB/16.04MB 79de921bba64: Loading layer [==================================================>] 28.25MB/28.25MB a4826ccd0680: Loading layer [==================================================>] 22.02kB/22.02kB 527c0492bb8a: Loading layer [==================================================>] 50.6MB/50.6MB Loaded image: goharbor/notary-server-photon:v2.0.0 da380ff7675f: Loading layer [==================================================>] 39.44MB/39.44MB 3e72063a3c12: Loading layer [==================================================>] 3.072kB/3.072kB 87063a362784: Loading layer [==================================================>] 59.9kB/59.9kB 12042912d563: Loading layer [==================================================>] 61.95kB/61.95kB Loaded image: goharbor/redis-photon:v2.0.0 497d39fd8ed4: Loading layer [==================================================>] 10.28MB/10.28MB Loaded image: goharbor/nginx-photon:v2.0.0 db89bcd4a7aa: Loading layer [==================================================>] 12.22MB/12.22MB a3c69d8e6487: Loading layer [==================================================>] 3.072kB/3.072kB 22888c961e12: Loading layer [==================================================>] 2.56kB/2.56kB 15c04c0d67b3: Loading layer [==================================================>] 46.5MB/46.5MB 5e59e5738914: Loading layer [==================================================>] 5.632kB/5.632kB 2fb21742e876: Loading layer [==================================================>] 51.2kB/51.2kB ebe005c22385: Loading layer [==================================================>] 47.32MB/47.32MB e91a77a1cc5d: Loading layer [==================================================>] 2.56kB/2.56kB Loaded image: goharbor/harbor-core:v2.0.0 c9ad3414e408: Loading layer [==================================================>] 63.57MB/63.57MB 0aea7ae12d77: Loading layer [==================================================>] 60.58MB/60.58MB c3be2cda3349: Loading layer [==================================================>] 5.632kB/5.632kB 970c1e4372ae: Loading layer [==================================================>] 2.048kB/2.048kB 51e00ddbcdac: Loading layer [==================================================>] 2.56kB/2.56kB 27d44e884cd0: Loading layer [==================================================>] 2.56kB/2.56kB 3086c2ee0489: Loading layer [==================================================>] 2.56kB/2.56kB efd18d9ef79c: Loading layer [==================================================>] 10.24kB/10.24kB Loaded image: goharbor/harbor-db:v2.0.0 ad0a4ed99dd0: Loading layer [==================================================>] 12.22MB/12.22MB 50121125e459: Loading layer [==================================================>] 3.072kB/3.072kB 6d05b39a8c44: Loading layer [==================================================>] 2.56kB/2.56kB 5380ddc5210f: Loading layer [==================================================>] 35.68MB/35.68MB e8053e60aee7: Loading layer [==================================================>] 36.5MB/36.5MB Loaded image: goharbor/harbor-jobservice:v2.0.0 9fefe33a31db: Loading layer [==================================================>] 9.741MB/9.741MB a52a9b417697: Loading layer [==================================================>] 3.584kB/3.584kB 9b6c54642038: Loading layer [==================================================>] 3.072kB/3.072kB 6a32c528face: Loading layer [==================================================>] 20.34MB/20.34MB 526552ecb5a3: Loading layer [==================================================>] 9.317MB/9.317MB bc3e72205f25: Loading layer [==================================================>] 30.48MB/30.48MB Loaded image: goharbor/trivy-adapter-photon:v2.0.0 51193d3ba093: Loading layer [==================================================>] 77.29MB/77.29MB 398b7c3413c0: Loading layer [==================================================>] 48.31MB/48.31MB cb902b44bae6: Loading layer [==================================================>] 2.56kB/2.56kB 11d3bf655c22: Loading layer [==================================================>] 1.536kB/1.536kB 3d373d988076: Loading layer [==================================================>] 18.43kB/18.43kB 755d5115a4fd: Loading layer [==================================================>] 3.751MB/3.751MB 5d456b2e2b47: Loading layer [==================================================>] 249.3kB/249.3kB Loaded image: goharbor/prepare:v2.0.0 2128feaae029: Loading layer [==================================================>] 10.28MB/10.28MB c1e2c6faf4a4: Loading layer [==================================================>] 8.487MB/8.487MB 8728e424e45b: Loading layer [==================================================>] 178.7kB/178.7kB 243de4b81324: Loading layer [==================================================>] 157.2kB/157.2kB 1909dd7d54dc: Loading layer [==================================================>] 33.28kB/33.28kB e91e103cac7d: Loading layer [==================================================>] 17.41kB/17.41kB ef43ac036ce0: Loading layer [==================================================>] 15.36kB/15.36kB 3205feaa4e7b: Loading layer [==================================================>] 3.584kB/3.584kB Loaded image: goharbor/harbor-portal:v2.0.0 [Step 3]: preparing environment ... [Step 4]: preparing harbor configs ... prepare base dir is set to /app/docker.soulteary.com/harbor WARNING:root:WARNING: HTTP protocol is insecure. Harbor will deprecate http protocol in the future. Please make sure to upgrade to https Generated configuration file: /config/log/logrotate.conf Generated configuration file: /config/log/rsyslog_docker.conf Generated configuration file: /config/nginx/nginx.conf Generated configuration file: /config/core/env Generated configuration file: /config/core/app.conf Generated configuration file: /config/registry/config.yml Generated configuration file: /config/registryctl/env Generated configuration file: /config/registryctl/config.yml Generated configuration file: /config/db/env Generated configuration file: /config/jobservice/env Generated configuration file: /config/jobservice/config.yml Generated and saved secret to file: /data/secret/keys/secretkey Successfully called func: create_root_cert Generated configuration file: /compose_location/docker-compose.yml Clean up the input dir [Step 5]: starting Harbor ... Creating network "harbor_harbor" with the default driver Creating harbor-log ... done Creating harbor-db ... done Creating harbor-portal ... done Creating redis ... done Creating registry ... done Creating registryctl ... done Creating harbor-core ... done Creating nginx ... ... ``` 可以看到安装脚本流程为:检查基础环境,然后将所需要的容器镜像导入,接着初始化配置,最后启动应用。 当应用启动完毕,访问之前配置好的域名, harbor 就安装完毕了。 ## 搭配 Traefik 使用 关于 Traefik 的实战应用,之前已经写过不少[文章](https://soulteary.com/tags/traefik.html),让 Harbor 结合 Traefik 一起使用也很容易。 ### 修改 Harbor 容器编排配置 在执行 `install.sh` 之后,harbor 默认生成的配置如下: ```yaml proxy: image: goharbor/nginx-photon:v2.0.0 container_name: nginx restart: always cap_drop: - ALL cap_add: - CHOWN - SETGID - SETUID - NET_BIND_SERVICE volumes: - ./common/config/nginx:/etc/nginx:z - type: bind source: ./common/config/shared/trust-certificates target: /harbor_cust_cert networks: - harbor dns_search: . ports: - 80:8080 depends_on: - registry - core - portal - log logging: driver: "syslog" options: syslog-address: "tcp://127.0.0.1:1514" tag: "proxy" networks: harbor: external: false ``` 我们需要修改三处: 1. 添加全局外部网络 2. 为 harbor Web 服务添加网络 3. 声明 Traefik 配置 指定全局网络和 Harbor Web 服务网络只需要多几行声明即可。 ```yaml proxy: image: goharbor/nginx-photon:v2.0.0 ... networks: - harbor - traefik dns_search: . ... networks: traefik: external: true harbor: external: false ``` 而 Traefik 配置,参考我们之前的文章,也不难写出: ```yaml labels: - "traefik.enable=true" - "traefik.docker.network=traefik" - "traefik.http.routers.www-harbor.middlewares=https-redirect@file" - "traefik.http.routers.www-harbor.entrypoints=http" - "traefik.http.routers.www-harbor.rule=Host(`$DOCKER_DOMAIN_NAME`)" - "traefik.http.routers.ssl-harbor.middlewares=content-compress@file" - "traefik.http.routers.ssl-harbor.entrypoints=https" - "traefik.http.routers.ssl-harbor.tls=true" - "traefik.http.routers.ssl-harbor.rule=Host(`$DOCKER_DOMAIN_NAME`)" - "traefik.http.services.ngx-harbor-backend.loadbalancer.server.scheme=http" - "traefik.http.services.ngx-harbor-backend.loadbalancer.server.port=8080" ``` 需要注意的是,如果你在过程中修改了 harbor.yml 配置,需要参考“重新安装”小节进行数据清理。 ### 配合SLB 使用 前文提过,生产环境如果使用 SLB 或者使用其他应用统一提供 SSL 接入,那么这里的 Traefik 配置则要进行调整。 ```yaml labels: - "traefik.enable=true" - "traefik.docker.network=traefik" - "traefik.http.middlewares.harbor-bechind-proxy.headers.customrequestheaders.X-Forwarded-Proto=https" - "traefik.http.routers.harbor-web.entrypoints=http" - "traefik.http.routers.harbor-web.rule=Host(`$DOCKER_DOMAIN_NAME`)" - "traefik.http.routers.harbor-web.service=harbor-backend" - "traefik.http.routers.harbor-web.middlewares=harbor-bechind-proxy" - "traefik.http.services.harbor-backend.loadbalancer.server.scheme=http" - "traefik.http.services.harbor-backend.loadbalancer.server.port=8080" ``` 一切就绪后,使用 `docker-compose up -d` 启动即可。 ```yaml docker-compose up -d Creating network "harbor_harbor" with the default driver Creating harbor-log ... done Creating harbor-db ... done Creating harbor-portal ... done Creating registryctl ... done Creating redis ... done Creating registry ... done Creating harbor-core ... done Creating harbor-jobservice ... done Creating nginx ... done ``` 顺利启动后,使用域名访问 harbor。 ![Harbor 登陆界面](https://attachment.soulteary.com/2020/05/23/harbor-login.png) 在登陆界面使用用户名 **admin** 和之前 **harbor.yml** 中配置的密码登陆即可。 ![Harbor 默认控制后台](https://attachment.soulteary.com/2020/05/23/harbor-dashboard.png) ## 重新安装 当修改 `harbor.yml` 后,我们需要执行 `bash prepare`,让配置能够得到更新。当然,历史存在的容器 container 也需要清理,除了使用 `docker rm` 进行清理外,还可以使用 `docker system prune` 进行清理。 ## 最后 接下来对 Nexus 仓库中容器镜像迁移 Harbor ,以及容器镜像安全管理 ,欢迎一起讨论沟通。 --EOF