From de402ea724d228b3d2fc8e0cf28aac6579e235b8 Mon Sep 17 00:00:00 2001 From: Scars Date: Mon, 19 Jan 2026 10:05:17 +0800 Subject: [PATCH] feat: Support batch import for Docker images (#11640) * feat: Support batch import for Docker images * perf: Avoid duplicate Docker client creation in ImageLoad * style: Remove unnecessary comments in FileList component --- agent/app/dto/image.go | 4 +- agent/app/service/image.go | 52 ++++++++------- frontend/src/api/interface/container.ts | 2 +- frontend/src/components/file-list/index.vue | 66 ++++++++++++++++--- .../src/views/container/image/load/index.vue | 12 ++-- 5 files changed, 98 insertions(+), 38 deletions(-) diff --git a/agent/app/dto/image.go b/agent/app/dto/image.go index ad2bb8873..e8c1daa6d 100644 --- a/agent/app/dto/image.go +++ b/agent/app/dto/image.go @@ -21,8 +21,8 @@ type ImageInfo struct { } type ImageLoad struct { - TaskID string `json:"taskID"` - Path string `json:"path" validate:"required"` + TaskID string `json:"taskID"` + Paths []string `json:"paths" validate:"required,dive,required"` } type ImageBuild struct { diff --git a/agent/app/service/image.go b/agent/app/service/image.go index 25509cfe9..2f1e43312 100644 --- a/agent/app/service/image.go +++ b/agent/app/service/image.go @@ -321,36 +321,44 @@ func (u *ImageService) ImagePull(req dto.ImagePull) error { } func (u *ImageService) ImageLoad(req dto.ImageLoad) error { - taskItem, err := task.NewTaskWithOps(req.Path, task.TaskImport, task.TaskScopeImage, req.TaskID, 1) + taskItem, err := task.NewTaskWithOps(strings.Join(req.Paths, ","), task.TaskImport, task.TaskScopeImage, req.TaskID, 1) if err != nil { return fmt.Errorf("new task for image import failed, err: %v", err) } - taskItem.AddSubTask(i18n.GetWithName("TaskImport", req.Path), func(t *task.Task) error { - file, err := os.Open(req.Path) - if err != nil { - return err - } - defer file.Close() + + go func() { client, err := docker.NewDockerClient() if err != nil { - return err + taskItem.Log("Failed to create Docker client: " + err.Error()) + return } defer client.Close() - res, err := client.ImageLoad(context.TODO(), file) - if err != nil { - return err + + for _, itemPath := range req.Paths { + currentPath := itemPath + itemName := path.Base(currentPath) + taskItem.AddSubTask(i18n.GetWithName("TaskImport", itemName), func(t *task.Task) error { + taskItem.Logf("----------------- %s -----------------", itemName) + file, err := os.Open(currentPath) + if err != nil { + return err + } + defer file.Close() + res, err := client.ImageLoad(context.TODO(), file) + if err != nil { + return err + } + defer res.Body.Close() + content, err := io.ReadAll(res.Body) + if err != nil { + return err + } + if strings.Contains(string(content), "Error") { + return errors.New(string(content)) + } + return nil + }, nil) } - defer res.Body.Close() - content, err := io.ReadAll(res.Body) - if err != nil { - return err - } - if strings.Contains(string(content), "Error") { - return errors.New(string(content)) - } - return nil - }, nil) - go func() { _ = taskItem.Execute() }() return nil diff --git a/frontend/src/api/interface/container.ts b/frontend/src/api/interface/container.ts index c0e4a5dcb..def8dd319 100644 --- a/frontend/src/api/interface/container.ts +++ b/frontend/src/api/interface/container.ts @@ -224,7 +224,7 @@ export namespace Container { } export interface ImageLoad { taskID: string; - path: string; + paths: Array; } export interface ImageSave { taskID: string; diff --git a/frontend/src/components/file-list/index.vue b/frontend/src/components/file-list/index.vue index 24219fa87..e80355e0d 100644 --- a/frontend/src/components/file-list/index.vue +++ b/frontend/src/components/file-list/index.vue @@ -105,7 +105,7 @@
-
+
{{ $t('file.currentSelect') }} @@ -115,6 +115,23 @@
+
+ {{ $t('file.currentSelect') }} + + +
+ {{ item.path }} +
+
+
+