query a docker registry (hub.docker.com) using go docker client without docker daemon dependency

huangapple go评论109阅读模式
英文:

query a docker registry (hub.docker.com) using go docker client without docker daemon dependency

问题

我正在尝试使用Go访问Docker注册表(公共或私有)。我需要一个简单的程序,可以访问任何注册表并验证镜像是否存在。

我查看了Go中可用的Docker客户端https://pkg.go.dev/github.com/docker/docker@v20.10.11+incompatible/client

但问题是,这个客户端需要运行Docker守护程序才能工作。是否有任何方法可以在不依赖底层Docker引擎的情况下查询Docker注册表(例如:hub.docker.com)?

我的想法是在Docker容器上运行此程序,并且容器内部不会运行任何Docker引擎。我不想在Docker内部运行Docker或任何其他类型的黑客。我只想连接到注册表并查询镜像。请不要引用Stack Overflow中的其他问题。没有人回答过这个问题。

这是我目前的进展:

  1. package main
  2. import (
  3. "context"
  4. "encoding/base64"
  5. "encoding/json"
  6. "fmt"
  7. "github.com/docker/docker/api/types/filters"
  8. "time"
  9. "github.com/docker/docker/api/types"
  10. "github.com/docker/docker/client"
  11. )
  12. func main() {
  13. cli, err := client.NewClientWithOpts(client.WithHost("https://hub.docker.com"), client.WithAPIVersionNegotiation())
  14. if err != nil {
  15. fmt.Println(err.Error())
  16. return
  17. }
  18. err = imagemanifest(cli)
  19. if err != nil {
  20. fmt.Println(err)
  21. }
  22. err = imageSearch(cli)
  23. }
  24. func imagemanifest(dockerClient *client.Client) error {
  25. var authConfig = types.AuthConfig{
  26. Username: "amokkara",
  27. Password: "M@vr1ck2009",
  28. ServerAddress: "https://index.docker.io/v2/",
  29. }
  30. ctx, cancel := context.WithTimeout(context.Background(), time.Second*1200)
  31. defer cancel()
  32. authConfigBytes, _ := json.Marshal(authConfig)
  33. authConfigEncoded := base64.URLEncoding.EncodeToString(authConfigBytes)
  34. ctx, cancel = context.WithTimeout(context.Background(), time.Second*1200)
  35. defer cancel()
  36. searchres, err := dockerClient.DistributionInspect(ctx, "amokkara/amokkara:3", authConfigEncoded)
  37. if err != nil {
  38. return err
  39. }
  40. fmt.Println(searchres.Descriptor.Digest.String())
  41. return nil
  42. }

如果我像这样初始化客户端:

  1. cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())

这样可以工作,因为它使用底层的Docker守护程序(在我的情况下是Docker桌面)来查询注册表。但是,如果使用以下方式创建客户端:

  1. client.NewClientWithOpts(client.WithHost("https://hub.docker.com"), client.WithAPIVersionNegotiation())

它会失败并返回404错误。这个客户端是否需要Docker守护程序才能工作?如果是这样,是否有其他方法可以查询注册表?请帮助我解决这个问题。

英文:

I'm trying to access a docker registry (public or private) using Go. A simple program which can access any registry and verify if an image is present.

I looked at docker client available in Go https://pkg.go.dev/github.com/docker/docker@v20.10.11+incompatible/client

But the problem is, this client needs a docker daemon running in order to work. Is there any way to query a docker registry (ex: hub.docker.com) without any dependency on underlying docker engine?

My idea is to run this program on a docker container and there wont be any docker engine running inside a container. And I don't want to run docker inside docker or any sort of hack. I just want to connect to a registry and query an image. And please don't quote other questions in stack overflow. No one has answered this.

This is what I have done so far

  1. import (
  2. "context"
  3. "encoding/base64"
  4. "encoding/json"
  5. "fmt"
  6. "github.com/docker/docker/api/types/filters"
  7. "time"
  8. "github.com/docker/docker/api/types"
  9. "github.com/docker/docker/client"
  10. )
  11. func main() {
  12. cli, err := client.NewClientWithOpts(client.WithHost("https://hub.docker.com"), client.WithAPIVersionNegotiation())
  13. if err != nil {
  14. fmt.Println(err.Error())
  15. return
  16. }
  17. err = imagemanifest(cli)
  18. if err != nil {
  19. fmt.Println(err)
  20. }
  21. err = imageSearch(cli)
  22. }
  23. func imagemanifest(dockerClient *client.Client) error {
  24. var authConfig = types.AuthConfig{
  25. Username: "amokkara",
  26. Password: "M@vr1ck2009",
  27. ServerAddress: "https://index.docker.io/v2/",
  28. }
  29. ctx, cancel := context.WithTimeout(context.Background(), time.Second*1200)
  30. defer cancel()
  31. authConfigBytes, _ := json.Marshal(authConfig)
  32. authConfigEncoded := base64.URLEncoding.EncodeToString(authConfigBytes)
  33. ctx, cancel = context.WithTimeout(context.Background(), time.Second*1200)
  34. defer cancel()
  35. searchres , err := dockerClient.DistributionInspect(ctx,"amokkara/amokkara:3",authConfigEncoded)
  36. if err != nil {
  37. return err
  38. }
  39. fmt.Println(searchres.Descriptor.Digest.String())
  40. return nil
  41. }

If I initialize client like this

cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())

This works because its using underlying docker daemon (in my case docker desktop) to query the registry. But if create client using

client.NewClientWithOpts(client.WithHost("https://hub.docker.com"), client.WithAPIVersionNegotiation())

it fails giving 404 error. Does this client require a docker daemon to work. If so, is there any other way i can query a registry? Please help me with this.

答案1

得分: 0

Skopeo是处理无守护程序的注册表的领先软件。

它也是用Go语言编写的。

你可以参考inspect.go

请注意,你不需要使用github.com/docker/docker/*模块,而是使用github.com/containers/*,具体来说是https://github.com/containers/image。

英文:

Skopeo is the leader software on dealing with registries without daemon.

It's also written with Go.

You can inspire from inspect.go

Note that, you don't need to use github.com/docker/docker/* modules, but it will be github.com/containers/*, and namely https://github.com/containers/image

huangapple
  • 本文由 发表于 2021年12月7日 12:33:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/70254976.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定