Как правильно аутентифицировать библиотеку golang клиента Docker в реестре gcr.io? - PullRequest
0 голосов
/ 02 октября 2019

У меня есть необходимость программно (используя golang) войти в реестр gcr.io с помощью этой библиотеки пакетов https://godoc.org/github.com/docker/docker/client

Я пробовал использовать его, я могу успешно войти, но после отправки изображения на мойРеестр проекта gcr.io, там сказано:

{"errorDetail":{"message":"unauthorized: You don't have the needed permissions to perform this operation, and you may have invalid credentials. To authenticate your request, follow the steps in: https://cloud.google.com/container-registry/docs/advanced-authentication"},"error":"unauthorized: You don't have the needed permissions to perform this operation, and you may have invalid credentials. To authenticate your request, follow the steps in: https://cloud.google.com/container-registry/docs/advanced-authentication"}

Мой код выглядит так

package client
import (
    "context"
    "fmt"
    "io"
    "os"

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

type Service struct{
    DockerClient *dockerClient.Client
}

type CopyImageOptions struct {
    DestRegistryAuth    string
}
type DockerImageService interface {
    CopyImage(ctx context.Context, source, dest string, option CopyImageOptions)
}

// NewDockerClient returns a client
func NewDockerClient() *Service {
    cli, err := dockerClient.NewEnvClient()
    if err != nil {
        panic(err)
    }
    return &Service{DockerClient: cli}
}

func (s *Service) CopyImage(ctx context.Context, source, dest string, option CopyImageOptions) error {

    rc, err := s.DockerClient.ImagePull(ctx, source, types.ImagePullOptions{})

    if err != nil{
        return fmt.Errorf("error when pulling source image. err: %v", err)
    }
    defer rc.Close()

    io.Copy(os.Stdout, rc)


    destClient := NewDockerClient()

    if option.DestRegistryAuth != ""  {
        //current use case we can assume that the dest is on asia.gcr.io
        status, err := destClient.DockerClient.RegistryLogin(ctx, types.AuthConfig{
            Username:      "oauth2accesstoken",
            Password:      option.DestRegistryAuth,
            ServerAddress: "asia.gcr.io",
        })
        if err != nil{
            return fmt.Errorf("error when login to destination image registry. err: %v", err)
        }

        fmt.Println(status)
    }
    err = destClient.DockerClient.ImageTag(ctx, source, dest)
    if err != nil {
        return fmt.Errorf("error when tagging image. err: %v", err)
    }
    rc, err = destClient.DockerClient.ImagePush(ctx, dest, types.ImagePushOptions{
        RegistryAuth: option.DestRegistryAuth,
    })

    if err != nil{
        return fmt.Errorf("error when pushing image to destionation. err: %v", err)
    }
    defer rc.Close()

    io.Copy(os.Stdout, rc)
    return nil
}

Вы можете взглянуть на метод CopyImage, где назначен option.DestRegistryAuthс выходом gcloud auth print-access-token. Имя пользователя установлено в «oauth2accesstoken», потому что я следовал этой инструкции: https://cloud.google.com/container-registry/docs/advanced-authentication

Что касается параметра source, предполагается, что он из публичного реестра, например docker.io/library/alpine:3.10, поэтомумы можем вытащить его без настройки токена авторизации. Однако для параметра dest в настоящее время это изображение в моем личном реестре, например: asia.gcr.io/<gcp-project-id>/alpine:3.10

Кроме того, gcloud auth print-access-token вызывается после того, как я сделал gcloud auth login, и у меня уже было полное разрешение наполучить доступ к моему личному реестру asia.gcr.io (назначенному на уровне сегмента).

Теперь странно то, что я могу успешно нажать его с помощью команды docker push, сразу после do docker login, описанной здесь https://cloud.google.com/container-registry/docs/advanced-authentication.

Любой совет?

1 Ответ

1 голос
/ 02 октября 2019

Хорошо, я только что узнал, в чем заключается ошибка в моем коде выше. Я понял это после просмотра примера кода для извлечения изображения из частного реестра здесь: https://docs.docker.com/develop/sdk/examples/#pull-an-image-with-authentication

Как выясняется, аргумент RegistryAuth в типах. Параметры ImagePush ожидаютстрока кодировки base64.

Итак, с помощью этого кода я могу успешно отправить локальное изображение в свой личный реестр.

    authConfig := types.AuthConfig{
        Username: "oauth2accesstoken",
        Password: option.DestRegistryAuth,
    }
    encodedJSON, err := json.Marshal(authConfig)
    if err != nil {
        return fmt.Errorf("error when encoding authConfig. err: %v", err)
    }

    authStr := base64.URLEncoding.EncodeToString(encodedJSON)

    rc, err = destClient.DockerClient.ImagePush(ctx, dest, types.ImagePushOptions{
        RegistryAuth: authStr,
    })
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...