Agu*_*ama 4 go docker google-cloud-platform
我需要使用这个包库https://godoc.org/github.com/docker/docker/client以编程方式(使用 golang)登录到 gcr.io docker 注册表
我试过使用它,我可以成功登录,但是在将图像推送到我的 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"}
Run Code Online (Sandbox Code Playgroud)
我的代码看起来像这样
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
}
Run Code Online (Sandbox Code Playgroud)
您可以查看CopyImage方法,其中option.DestRegistryAuth分配了 output 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 注册表(在存储桶级别分配)的完全权限。
现在奇怪的是,在https://cloud.google.com/container-registry/docs/advanced-authentication 中描述docker push之后,我可以使用命令成功推送它。docker login
有什么建议吗?
好的,我刚刚发现我上面的代码有什么错误。在查看从私有注册表中提取图像的示例代码后,我意识到了这一点:https : //docs.docker.com/develop/sdk/examples/#pull-an-image-with-authentication
事实证明,RegistryAuthtypes.ImagePush 选项中的arg 需要一个 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,
})
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2311 次 |
| 最近记录: |