From 18719f911242d64a28a4288d62accb53d80440ea Mon Sep 17 00:00:00 2001 From: ssongliu <73214554+ssongliu@users.noreply.github.com> Date: Wed, 26 Jun 2024 14:28:49 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E9=95=9C=E5=83=8F=E6=8B=89=E5=8F=96?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E7=B3=BB=E7=BB=9F=E8=AE=A4=E8=AF=81=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=20(#5571)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs #5537 --- backend/app/service/container.go | 16 ++++--- backend/app/service/image.go | 55 ++++++++++++++++++++++- backend/utils/postgresql/client/remote.go | 3 +- 3 files changed, 65 insertions(+), 9 deletions(-) diff --git a/backend/app/service/container.go b/backend/app/service/container.go index b40421392..ae7d25d6e 100644 --- a/backend/app/service/container.go +++ b/backend/app/service/container.go @@ -6,7 +6,6 @@ import ( "encoding/base64" "encoding/json" "fmt" - "github.com/gin-gonic/gin" "io" "net/http" "net/url" @@ -21,6 +20,8 @@ import ( "time" "unicode/utf8" + "github.com/gin-gonic/gin" + "github.com/pkg/errors" "github.com/1Panel-dev/1Panel/backend/app/dto" @@ -988,12 +989,12 @@ func checkImageExist(client *client.Client, imageItem string) bool { return false } -func pullImages(ctx context.Context, client *client.Client, image string) error { - options := types.ImagePullOptions{} +func pullImages(ctx context.Context, client *client.Client, imageName string) error { + options := image.PullOptions{} repos, _ := imageRepoRepo.List() if len(repos) != 0 { for _, repo := range repos { - if strings.HasPrefix(image, repo.DownloadUrl) && repo.Auth { + if strings.HasPrefix(imageName, repo.DownloadUrl) && repo.Auth { authConfig := registry.AuthConfig{ Username: repo.Username, Password: repo.Password, @@ -1006,8 +1007,13 @@ func pullImages(ctx context.Context, client *client.Client, image string) error options.RegistryAuth = authStr } } + } else { + hasAuth, authStr := loadAuthInfo(imageName) + if hasAuth { + options.RegistryAuth = authStr + } } - out, err := client.ImagePull(ctx, image, options) + out, err := client.ImagePull(ctx, imageName, options) if err != nil { return err } diff --git a/backend/app/service/image.go b/backend/app/service/image.go index 105cecbc7..d3273ec3d 100644 --- a/backend/app/service/image.go +++ b/backend/app/service/image.go @@ -24,6 +24,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/registry" "github.com/docker/docker/pkg/archive" + "github.com/docker/docker/pkg/homedir" ) type ImageService struct{} @@ -253,10 +254,15 @@ func (u *ImageService) ImagePull(req dto.ImagePull) (string, error) { if err != nil { return "", err } + options := image.PullOptions{} if req.RepoID == 0 { + hasAuth, authStr := loadAuthInfo(req.ImageName) + if hasAuth { + options.RegistryAuth = authStr + } go func() { defer file.Close() - out, err := client.ImagePull(context.TODO(), req.ImageName, types.ImagePullOptions{}) + out, err := client.ImagePull(context.TODO(), req.ImageName, options) if err != nil { global.LOG.Errorf("image %s pull failed, err: %v", req.ImageName, err) return @@ -271,7 +277,6 @@ func (u *ImageService) ImagePull(req dto.ImagePull) (string, error) { if err != nil { return "", err } - options := image.PullOptions{} if repo.Auth { authConfig := registry.AuthConfig{ Username: repo.Username, @@ -464,3 +469,49 @@ func checkUsed(imageID string, containers []types.Container) bool { } return false } + +func loadAuthInfo(image string) (bool, string) { + if !strings.Contains(image, "/") { + return false, "" + } + homeDir := homedir.Get() + confPath := path.Join(homeDir, ".docker/config.json") + configFileBytes, err := os.ReadFile(confPath) + if err != nil { + return false, "" + } + var config dockerConfig + if err = json.Unmarshal(configFileBytes, &config); err != nil { + return false, "" + } + var ( + user string + passwd string + ) + imagePrefix := strings.Split(image, "/")[0] + if val, ok := config.Auths[imagePrefix]; ok { + itemByte, _ := base64.StdEncoding.DecodeString(val.Auth) + itemStr := string(itemByte) + if strings.Contains(itemStr, ":") { + user = strings.Split(itemStr, ":")[0] + passwd = strings.Split(itemStr, ":")[1] + } + } + authConfig := registry.AuthConfig{ + Username: user, + Password: passwd, + } + encodedJSON, err := json.Marshal(authConfig) + if err != nil { + return false, "" + } + authStr := base64.URLEncoding.EncodeToString(encodedJSON) + return true, authStr +} + +type dockerConfig struct { + Auths map[string]authConfig `json:"auths"` +} +type authConfig struct { + Auth string `json:"auth"` +} diff --git a/backend/utils/postgresql/client/remote.go b/backend/utils/postgresql/client/remote.go index 8b5722378..0b3b11c67 100644 --- a/backend/utils/postgresql/client/remote.go +++ b/backend/utils/postgresql/client/remote.go @@ -13,7 +13,6 @@ import ( "github.com/1Panel-dev/1Panel/backend/app/model" "github.com/1Panel-dev/1Panel/backend/global" - "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/image" "github.com/pkg/errors" @@ -300,7 +299,7 @@ func loadImageTag() (string, error) { itemTag = "postgres:16.1-alpine" ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute) defer cancel() - if _, err := client.ImagePull(ctx, itemTag, types.ImagePullOptions{}); err != nil { + if _, err := client.ImagePull(ctx, itemTag, image.PullOptions{}); err != nil { if ctx.Err() == context.DeadlineExceeded { return itemTag, buserr.New(constant.ErrPgImagePull) }