У меня есть необходимость программно (используя 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.
Любой совет?