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

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

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中的其他问题。没有人回答过这个问题。

这是我目前的进展:

package main

import (
	"context"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"github.com/docker/docker/api/types/filters"
	"time"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/client"
)

func main() {
	cli, err := client.NewClientWithOpts(client.WithHost("https://hub.docker.com"), client.WithAPIVersionNegotiation())
	if err != nil {
		fmt.Println(err.Error())
		return
	}

	err = imagemanifest(cli)
	if err != nil {
		fmt.Println(err)
	}

	err = imageSearch(cli)
}

func imagemanifest(dockerClient *client.Client) error {
	var authConfig = types.AuthConfig{
		Username:      "amokkara",
		Password:      "M@vr1ck2009",
		ServerAddress: "https://index.docker.io/v2/",
	}

	ctx, cancel := context.WithTimeout(context.Background(), time.Second*1200)
	defer cancel()

	authConfigBytes, _ := json.Marshal(authConfig)
	authConfigEncoded := base64.URLEncoding.EncodeToString(authConfigBytes)

	ctx, cancel = context.WithTimeout(context.Background(), time.Second*1200)
	defer cancel()

	searchres, err := dockerClient.DistributionInspect(ctx, "amokkara/amokkara:3", authConfigEncoded)
	if err != nil {
		return err
	}

	fmt.Println(searchres.Descriptor.Digest.String())

	return nil
}

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

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

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

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


import (
	"context"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"github.com/docker/docker/api/types/filters"
	"time"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/client"
)

func main() {


	cli, err := client.NewClientWithOpts(client.WithHost("https://hub.docker.com"), client.WithAPIVersionNegotiation())
	if err != nil {
		fmt.Println(err.Error())
		return
	}


	err = imagemanifest(cli)
	if err != nil {
		fmt.Println(err)
	}

	err = imageSearch(cli)

}


func imagemanifest(dockerClient *client.Client) error {

	var authConfig = types.AuthConfig{
		Username:      "amokkara",
		Password:      "M@vr1ck2009",
		ServerAddress: "https://index.docker.io/v2/",
	}

	ctx, cancel := context.WithTimeout(context.Background(), time.Second*1200)
	defer cancel()

	authConfigBytes, _ := json.Marshal(authConfig)
	authConfigEncoded := base64.URLEncoding.EncodeToString(authConfigBytes)

	ctx, cancel = context.WithTimeout(context.Background(), time.Second*1200)
	defer cancel()


	searchres , err := dockerClient.DistributionInspect(ctx,"amokkara/amokkara:3",authConfigEncoded)
	if err != nil {
		return err
	}

	fmt.Println(searchres.Descriptor.Digest.String())

	return nil
}





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:

确定