dockergodocker-registry

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


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.


Solution

  • 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