Harbor 镜像仓库可以添加描述信息,像 Docker Hub 那样,浏览镜像仓库,就能大致了解镜像的用途及使用方法。但是手动维护描述信息会很麻烦,更好的方案是直接将代码仓库的 README.md
文件自动更新到描述信息。本文记录了一种在 Drone CI 中通过定制 kaniko 插件来自动更新 Harbor 仓库描述信息的方案。
Contents
方案
使用 Go 语言,新建 desc.go
,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
package main import ( "encoding/json" "net/http" "io/ioutil" "fmt" "flag" "bytes" "strings" "os" ) // Generated by curl-to-Go: https://mholt.github.io/curl-to-go type Payload struct { Description string `json:"description"` } func main () { api := flag.String("api", "http://harbor-api-proxy.intra.xx.com/api/repositories", "harbor api for repo description") desc := flag.String("desc", "README.md", "description filename") repo := flag.String("repo", "", "repo name") flag.Parse() if *repo == "" { fmt.Println("must provide repo name") os.Exit(1) } repository := strings.Replace(*repo, "/", "%2F", -1) // read description from desc file b, err := ioutil.ReadFile(*desc) if err != nil { fmt.Print(err) } str := string(b) data := Payload{Description: str} payloadBytes, err := json.Marshal(data) if err != nil { fmt.Print(err) } body := bytes.NewReader(payloadBytes) url := *api + "/" + repository req, err := http.NewRequest("PUT", url, body) if err != nil { fmt.Print(err) } req.Header.Set("Accept", "application/json") req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { fmt.Print(err) } fmt.Println(resp.Status) defer resp.Body.Close() } |
编译
1 |
CGO_ENABLED go build -o bin/desc desc.go |
将 bin/desc
添加到镜像中:
1 |
ADD bin/desc /kaniko/desc |
desc
工具的用法:
1 2 3 4 5 6 7 8 |
# ./bin/desc -h Usage of ./bin/desc: -api string harbor api for repo description (default "http://harbor-api-proxy.intra.xx.com/api/repositories") -desc string description filename (default "README.md") -repo string repo name |
在 plugin.sh
中使用 desc
:
1 2 |
# update repo description. use harbor api. Should run after image push. Otherwise in first build harbor api will return 404 Not Found /kaniko/desc -api "${PLUGIN_DESC_API:-http://harbor-api-proxy.intra.xx.com/api/repositories}" -desc "${PLUGIN_DESC_FILE:-README.md}" -repo "${PLUGIN_REPO:-}" |
更进一步,还可以考虑在此步骤中将代码仓库的自动信息附加到 README.md
的结尾,方便从镜像仓库快速跳转到代码仓库查看 Dockerfile 等需求。
1 2 3 4 |
# update repo description. use harbor api. Should run after image push. Otherwise in first build harbor api will return 404 Not Found echo -e "\n\n# Additional Info\n\n| Item | Value |\n|-|-|\n|Source Code|${DRONE_GIT_HTTP_URL}|\n|Commit SHA|${DRONE_COMMIT_SHA}|\n|Commit Author|${DRONE_COMMIT_AUTHOR_NAME}|\n|Commit Branch|${DRONE_COMMIT_BRANCH}|\n|Build Link|${DRONE_BUILD_LINK}|\n\n" >> ${PLUGIN_DESC_FILE:-README.md} echo "Update repository description: " /kaniko/desc -api "${PLUGIN_DESC_API:-http://harbor-api-proxy.intra.xx.com/api/repositories}" -desc "${PLUGIN_DESC_FILE:-README.md}" -repo "${PLUGIN_REPO:-}" |
用法
通过 kaniko 参数可以设置 DESC_API
及 DESC_FILE
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
kind: pipeline name: default steps: - name: publish image: ops/drone-kaniko settings: registry: registry.example.com # if not provided index.docker.io is supposed repo: registry.example.com/example-project desc_api: https://harbor-proxy.com desc_file: README.md tags: ${DRONE_COMMIT_SHA} cache: true skip_tls_verify: false # set to true for testing registries ONLY with self-signed certs build_args: - COMMIT_SHA=${DRONE_COMMIT_SHA} - COMMIT_AUTHOR_EMAIL=${DRONE_COMMIT_AUTHOR_EMAIL} username: from_secret: docker-username password: from_secret: docker-password |
更好的方式是定制 desc
工具,使用符合自身业务的 DESC_API
和 DESC_FILE
默认值,这样就可以不用在 yaml
中指定了。
演示
Harbor 中的效果如图所示。

harbor proxy
上文 desc
中调用的 DESC_API
是没有认证的,实际上是一个代理。在我的场景下,使用 OIDC 登录 Harbor,没有理解 OIDC 方式下调用 API 的方法,所以就弄了个代理,用 admin 账号调用 API,并且限制只能 CI 服务器的 IP 调用。应该还有更好的方案来调用 Harbor API。
Harbor Proxy 通过 Nginx 实现,核心配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# need resolver resolver 169.169.0.2; upstream harbor-core { server cr-harbor-core.intra.svc.cluster.local:80; keepalive 512; } server { listen 80; set_real_ip_from 0.0.0.0/0; #真实服务器上一级代理的IP地址或者IP段,可以写多行。 real_ip_header X-Forwarded-For; #从哪个header头检索出要的IP地址。 real_ip_recursive on; #递归的去除所配置中的可信IP。 include allow.conf; location ~ /api/repositories { if ($request_method !~ ^(PUT)$) {return 403;} proxy_set_header Authorization $http_authorization; proxy_pass http://harbor-core; } location ~ /api { return 403; } } |
完整项目请参考 Github。
参考资料
1 2 |
1. https://github.com/banzaicloud/drone-kaniko/issues/18 2. https://github.com/ops-itop/harbor-proxy |
发表回复