使用Go访问远程Docker仓库

5
我需要使用Go语言和V2协议访问私有Docker注册表。我需要列出私有注册表中的仓库,获取它们所有的标签以及其他信息。我应该使用docker/distribution/registry/client吗?有没有这样一个任务的示例?我找不到...官方网站只提供HTTP API文档。
我已经编写了一些代码:
    registry, err := client.NewRegistry("https://registry-1.docker.io/", http.DefaultTransport)
    if err != nil {
        log.Error("Error creating the registry: {}", err)
        return
    }

    ctx := context.Background()

    entries := make([]string, 5)

    numFilled, err := registry.Repositories(ctx, entries, "")
    if err != io.EOF {
        log.Error("Error getting the registry: {}", err)
        return
    }

    log.Info("Number of repositories: {}", numFilled)

    _ = registry

当然,Docker仓库需要身份验证。但我该如何提供它?是否有一个文档来完成这项任务?
2个回答

4

这里的代码示例来自源代码包中的测试代码:


import (
    "github.com/docker/distribution/registry/client"
    "github.com/docker/distribution/registry/client/auth"
    "github.com/docker/distribution/registry/client/auth/challenge"
    "github.com/docker/distribution/registry/client/transport"
)
    
type regCredentialStore struct {
    username      string
    password      string
    refreshTokens map[string]string
}

func (tcs *regCredentialStore) Basic(*url.URL) (string, string) {
    return tcs.username, tcs.password
}

func (tcs *regCredentialStore) RefreshToken(u *url.URL, service string) string {
    return tcs.refreshTokens[service]
}

func (tcs *regCredentialStore) SetRefreshToken(u *url.URL, service string, token string) {
    if tcs.refreshTokens != nil {
        tcs.refreshTokens[service] = token
    }
}

func main() {
    creds := &regCredentialStore{username: "user", password: "pwd"}
    challengeManager := challenge.NewSimpleManager()
    _, err = ping(challengeManager, "https://registry-1.docker.io/v2/", "")
    if err != nil {
        .... exit .....
    }
    transport1 := transport.NewTransport(
        nil, auth.NewAuthorizer(challengeManager, auth.NewBasicHandler(creds)))
    reg, err := client.NewRegistry("https://registry-1.docker.io/", transport1)
    ...
}   

func ping(manager challenge.Manager, endpoint, versionHeader string) ([]auth.APIVersion, error) {
    resp, err := http.Get(endpoint)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    if err := manager.AddResponse(resp); err != nil {
        return nil, err
    }

    return auth.APIVersions(resp, versionHeader), err
}


1
你可以使用带有身份验证头部的简单http调用(因为它只是HTTP API),例如列出所选图像的标签:
req, _ := http.NewRequest("GET", "https://"+privateDockerRegistry+"/v2/"+dockerImage+"/tags/list", nil)
req.Header.Add("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(os.Getenv("DOCKER_USER")+":"+os.Getenv("DOCKER_PASSWORD"))))
req.Header.Add("Accept", "application/json")
resp, _ := client.Do(req)
...

你的意思是说Docker API没有认证方法吗?实际上,在docker/distribution/registry/client/中有一个auth文件夹,但我不知道如何使用它... - denn
@denn 我没有说过那个。我提到了 HTTP API = 可以用简单的 HTTP 调用来实现。 - Jan Garaj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接