从 Harbor 批量拉镜像,再推送到新的镜像仓库

128 阅读1分钟

原理是根据 Harbor 的 API, 来编历所有的项目和仓库, 依次将所有镜像所有 tag 都 Pull 到本地, 再 retag 后 push 到新的仓库中。

本来以为这种常见的需求, 网上应该有实现了, 但令人失望的发现全是抄的一个写错了的文章。 不得已, 只能自己动手写个轮子了。

文末有脚本, 不想看过程的可以直接跳至文末。

1. 打开 Harbor

先从 Harbor 跳转到 API 页面, 确认相应 API 是否和脚本使用的一致

image.png

2. 在 Harbor 的在线文档服务中找到对应 project\repository\tag 的 API

用到了如下三个 API

image.png

image.png

image.png

如果这些 API 版本有差异, 请自行调整脚本

token 可以从上面的 API 在线服务中获得

#! /bin/bash

set -x

URL="https://hub.xxx.com"
REGISTRYURL="hub.xxx.com"
token="ZW1xxxxxxxxxxxxx1bHQxIQ=="
NewRegistryRepo="xxx.cn-hangzhou.personal.cr.aliyuncs.com/yyy"

# 查询所有的projectId

# 用 curl 命令请求 API 拿到 ProjectId
curl -X 'GET' \
  ${URL}'/api/v2.0/projects?page=1&page_size=20&with_detail=true'  \
  -H 'accept: application/json' \
  -H 'authorization: Basic ${token}' \
  | jq -r '.[].name' \
  | while read -r name; do
      echo "project: ${name}"
      REPOS=`curl -X 'GET' \
            ${URL}'/api/v2.0/projects/'${name}'/repositories?page=1&page_size=100' \
            -H 'accept: application/json' \
            -H 'authorization: Basic '${token} \
            | jq -r '.[].name' | awk -F'/' '{print $2}' `
      for rp in ${REPOS}; do
        echo "repository: ${rp}"
        TAGS=`curl -X 'GET' \
          ${URL}'/api/v2.0/projects/'${name}'/repositories/'${rp}'/artifacts?page=1&page_size=100&with_tag=true&with_label=false&with_scan_overview=false&with_signature=false&with_immutable_status=false&with_accessory=false' \
          -H 'accept: application/json' \
          -H 'X-Accept-Vulnerabilities: application/vnd.security.vulnerability.report; version=1.1, application/vnd.scanner.adapter.vuln.report.harbor+json; version=1.0' \
          -H 'authorization: Basic '${token} \
          | jq -r '.[].tags[].name'`
        for t in ${TAGS}; do
          echo "tag: ${t}"
          image=${REGISTRYURL}"/"$name"/"${rp}":"${t}
          echo "start pull image: ${image}>>>>>>>>>>>"
          docker pull ${image}
          newimage=${NewRegistryRepo}"/"${rp}":"${t}
          docker tag ${image} ${newimage}
          docker push ${newimage}
        done
      done
done