fix: 镜像拉取同步系统认证信息 (#5571)

Refs #5537
This commit is contained in:
ssongliu 2024-06-26 14:28:49 +08:00 committed by GitHub
parent 0886bcd310
commit 18719f9112
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 65 additions and 9 deletions

View File

@ -6,7 +6,6 @@ import (
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/gin-gonic/gin"
"io" "io"
"net/http" "net/http"
"net/url" "net/url"
@ -21,6 +20,8 @@ import (
"time" "time"
"unicode/utf8" "unicode/utf8"
"github.com/gin-gonic/gin"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/app/dto"
@ -988,12 +989,12 @@ func checkImageExist(client *client.Client, imageItem string) bool {
return false return false
} }
func pullImages(ctx context.Context, client *client.Client, image string) error { func pullImages(ctx context.Context, client *client.Client, imageName string) error {
options := types.ImagePullOptions{} options := image.PullOptions{}
repos, _ := imageRepoRepo.List() repos, _ := imageRepoRepo.List()
if len(repos) != 0 { if len(repos) != 0 {
for _, repo := range repos { for _, repo := range repos {
if strings.HasPrefix(image, repo.DownloadUrl) && repo.Auth { if strings.HasPrefix(imageName, repo.DownloadUrl) && repo.Auth {
authConfig := registry.AuthConfig{ authConfig := registry.AuthConfig{
Username: repo.Username, Username: repo.Username,
Password: repo.Password, Password: repo.Password,
@ -1006,8 +1007,13 @@ func pullImages(ctx context.Context, client *client.Client, image string) error
options.RegistryAuth = authStr 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 { if err != nil {
return err return err
} }

View File

@ -24,6 +24,7 @@ import (
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/registry" "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/homedir"
) )
type ImageService struct{} type ImageService struct{}
@ -253,10 +254,15 @@ func (u *ImageService) ImagePull(req dto.ImagePull) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
options := image.PullOptions{}
if req.RepoID == 0 { if req.RepoID == 0 {
hasAuth, authStr := loadAuthInfo(req.ImageName)
if hasAuth {
options.RegistryAuth = authStr
}
go func() { go func() {
defer file.Close() 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 { if err != nil {
global.LOG.Errorf("image %s pull failed, err: %v", req.ImageName, err) global.LOG.Errorf("image %s pull failed, err: %v", req.ImageName, err)
return return
@ -271,7 +277,6 @@ func (u *ImageService) ImagePull(req dto.ImagePull) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
options := image.PullOptions{}
if repo.Auth { if repo.Auth {
authConfig := registry.AuthConfig{ authConfig := registry.AuthConfig{
Username: repo.Username, Username: repo.Username,
@ -464,3 +469,49 @@ func checkUsed(imageID string, containers []types.Container) bool {
} }
return false 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"`
}

View File

@ -13,7 +13,6 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/model" "github.com/1Panel-dev/1Panel/backend/app/model"
"github.com/1Panel-dev/1Panel/backend/global" "github.com/1Panel-dev/1Panel/backend/global"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/image" "github.com/docker/docker/api/types/image"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -300,7 +299,7 @@ func loadImageTag() (string, error) {
itemTag = "postgres:16.1-alpine" itemTag = "postgres:16.1-alpine"
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute) ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute)
defer cancel() 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 { if ctx.Err() == context.DeadlineExceeded {
return itemTag, buserr.New(constant.ErrPgImagePull) return itemTag, buserr.New(constant.ErrPgImagePull)
} }