From d90241729f4aa4af136b7e63680d05a3bc164dc6 Mon Sep 17 00:00:00 2001 From: zhoujunhong <1298308460@qq.com> Date: Thu, 13 Jun 2024 17:58:54 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=B9=E5=99=A8=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=88=B6=E4=BD=9C=E5=AE=B9=E5=99=A8=E9=95=9C?= =?UTF-8?q?=E5=83=8F=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/api/v1/container.go | 20 +++ backend/app/dto/container.go | 13 +- backend/app/service/container.go | 23 ++++ backend/router/ro_container.go | 1 + frontend/src/api/interface/container.ts | 8 ++ frontend/src/api/modules/container.ts | 3 + frontend/src/lang/modules/en.ts | 7 ++ frontend/src/lang/modules/tw.ts | 7 ++ frontend/src/lang/modules/zh.ts | 7 ++ .../container/container/commit/index.vue | 119 ++++++++++++++++++ .../src/views/container/container/index.vue | 12 ++ 11 files changed, 219 insertions(+), 1 deletion(-) create mode 100644 frontend/src/views/container/container/commit/index.vue diff --git a/backend/app/api/v1/container.go b/backend/app/api/v1/container.go index 78062c2d6..f62838ddf 100644 --- a/backend/app/api/v1/container.go +++ b/backend/app/api/v1/container.go @@ -346,6 +346,26 @@ func (b *BaseApi) ContainerRename(c *gin.Context) { helper.SuccessWithData(c, nil) } +// @Tags Container +// @Summary Commit Container +// @Description 容器提交生成新镜像 +// @Accept json +// @Param request body dto.ContainerCommit true "request" +// @Success 200 +// @Router /containers/commit [post] +func (b *BaseApi) ContainerCommit(c *gin.Context) { + var req dto.ContainerCommit + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + + if err := containerService.ContainerCommit(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, nil) +} + // @Tags Container // @Summary Operate Container // @Description 容器操作 diff --git a/backend/app/dto/container.go b/backend/app/dto/container.go index c7d252b73..36c05f884 100644 --- a/backend/app/dto/container.go +++ b/backend/app/dto/container.go @@ -1,6 +1,8 @@ package dto -import "time" +import ( + "time" +) type PageContainer struct { PageInfo @@ -122,6 +124,15 @@ type ContainerRename struct { NewName string `json:"newName" validate:"required"` } +type ContainerCommit struct { + ContainerId string `json:"containerID" validate:"required"` + ContainerName string `json:"containerName"` + NewImageName string `json:"newImageName"` + Comment string `json:"comment"` + Author string `json:"author"` + Pause bool `json:"pause"` +} + type ContainerPrune struct { PruneType string `json:"pruneType" validate:"required,oneof=container image volume network buildcache"` WithTagAll bool `json:"withTagAll"` diff --git a/backend/app/service/container.go b/backend/app/service/container.go index 53ec906e1..3104c1fe8 100644 --- a/backend/app/service/container.go +++ b/backend/app/service/container.go @@ -60,6 +60,7 @@ type IContainerService interface { ContainerListStats() ([]dto.ContainerListStats, error) LoadResourceLimit() (*dto.ResourceLimit, error) ContainerRename(req dto.ContainerRename) error + ContainerCommit(req dto.ContainerCommit) error ContainerLogClean(req dto.OperationWithName) error ContainerOperation(req dto.ContainerOperation) error ContainerLogs(wsConn *websocket.Conn, containerType, container, since, tail string, follow bool) error @@ -597,6 +598,28 @@ func (u *ContainerService) ContainerRename(req dto.ContainerRename) error { return client.ContainerRename(ctx, req.Name, req.NewName) } +func (u *ContainerService) ContainerCommit(req dto.ContainerCommit) error { + ctx := context.Background() + client, err := docker.NewDockerClient() + if err != nil { + return err + } + defer client.Close() + options := container.CommitOptions{ + Reference: req.NewImageName, + Comment: req.Comment, + Author: req.Author, + Changes: nil, + Pause: req.Pause, + Config: nil, + } + _, err = client.ContainerCommit(ctx, req.ContainerId, options) + if err != nil { + return fmt.Errorf("failed to commit container, err: %v", err) + } + return nil +} + func (u *ContainerService) ContainerOperation(req dto.ContainerOperation) error { var err error ctx := context.Background() diff --git a/backend/router/ro_container.go b/backend/router/ro_container.go index 657a7b7ea..27f536f24 100644 --- a/backend/router/ro_container.go +++ b/backend/router/ro_container.go @@ -31,6 +31,7 @@ func (s *ContainerRouter) InitRouter(Router *gin.RouterGroup) { baRouter.POST("/load/log", baseApi.LoadContainerLog) baRouter.POST("/inspect", baseApi.Inspect) baRouter.POST("/rename", baseApi.ContainerRename) + baRouter.POST("/commit", baseApi.ContainerCommit) baRouter.POST("/operate", baseApi.ContainerOperation) baRouter.POST("/prune", baseApi.ContainerPrune) diff --git a/frontend/src/api/interface/container.ts b/frontend/src/api/interface/container.ts index 44257eb08..55f0edae1 100644 --- a/frontend/src/api/interface/container.ts +++ b/frontend/src/api/interface/container.ts @@ -9,6 +9,14 @@ export namespace Container { name: string; newName: string; } + export interface ContainerCommit { + containerID: string; + containerName: string; + newImageName: string; + comment: string; + author: string; + pause: boolean; + } export interface ContainerSearch extends ReqPage { name: string; state: string; diff --git a/frontend/src/api/modules/container.ts b/frontend/src/api/modules/container.ts index 6090ec792..080a91809 100644 --- a/frontend/src/api/modules/container.ts +++ b/frontend/src/api/modules/container.ts @@ -21,6 +21,9 @@ export const updateContainer = (params: Container.ContainerHelper) => { export const upgradeContainer = (name: string, image: string, forcePull: boolean) => { return http.post(`/containers/upgrade`, { name: name, image: image, forcePull: forcePull }, TimeoutEnum.T_10M); }; +export const commitContainer = (params: Container.ContainerCommit) => { + return http.post(`/containers/commit`, params); +}; export const loadContainerInfo = (name: string) => { return http.post(`/containers/info`, { name: name }); }; diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index c04e9ee28..952dd3435 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -811,6 +811,13 @@ const message = { cleanImagesHelper: '( Clean up all images that are not used by any containers )', cleanContainersHelper: '( Clean up all stopped containers )', cleanVolumesHelper: '( Clean up all unused local volumes )', + + makeImage: 'Create Image', + newImageName: 'New Image Name', + commitMessage: 'Commit Message', + author: 'Author', + ifPause: 'Pause Container During Creation', + ifMakeImageWithContainer: 'Create New Image from This Container?', }, cronjob: { create: 'Create Cronjob', diff --git a/frontend/src/lang/modules/tw.ts b/frontend/src/lang/modules/tw.ts index 9b47d7e04..de9b5376e 100644 --- a/frontend/src/lang/modules/tw.ts +++ b/frontend/src/lang/modules/tw.ts @@ -776,6 +776,13 @@ const message = { cleanImagesHelper: '( 清理所有未被任何容器使用的鏡像 )', cleanContainersHelper: '( 清理所有處於停止狀態的容器 )', cleanVolumesHelper: '( 清理所有未被使用的本地存儲卷 )', + + makeImage: '製作鏡像', + newImageName: '新鏡像名稱', + commitMessage: '提交信息', + author: '作者', + ifPause: '製作過程中是否暫停容器', + ifMakeImageWithContainer: '是否根據此容器製作新鏡像?', }, cronjob: { create: '創建計劃任務', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index ea19c5835..db3dad369 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -777,6 +777,13 @@ const message = { cleanImagesHelper: '( 清理所有未被任何容器使用的镜像 )', cleanContainersHelper: '( 清理所有处于停止状态的容器 )', cleanVolumesHelper: '( 清理所有未被使用的本地存储卷 )', + + makeImage: '制作镜像', + newImageName: '新镜像名称', + commitMessage: '提交信息', + author: '作者', + ifPause: '制作过程中是否暂停容器', + ifMakeImageWithContainer: '是否根据此容器制作新镜像?', }, cronjob: { create: '创建计划任务', diff --git a/frontend/src/views/container/container/commit/index.vue b/frontend/src/views/container/container/commit/index.vue new file mode 100644 index 000000000..e654c7c84 --- /dev/null +++ b/frontend/src/views/container/container/commit/index.vue @@ -0,0 +1,119 @@ + + + diff --git a/frontend/src/views/container/container/index.vue b/frontend/src/views/container/container/index.vue index 54b3b112b..866feb19d 100644 --- a/frontend/src/views/container/container/index.vue +++ b/frontend/src/views/container/container/index.vue @@ -311,6 +311,7 @@ + @@ -323,6 +324,7 @@ import PruneDialog from '@/views/container/container/prune/index.vue'; import RenameDialog from '@/views/container/container/rename/index.vue'; import OperateDialog from '@/views/container/container/operate/index.vue'; import UpgradeDialog from '@/views/container/container/upgrade/index.vue'; +import CommitDialog from '@/views/container/container/commit/index.vue'; import MonitorDialog from '@/views/container/container/monitor/index.vue'; import ContainerLogDialog from '@/views/container/container/log/index.vue'; import TerminalDialog from '@/views/container/container/terminal/index.vue'; @@ -363,6 +365,7 @@ const paginationConfig = reactive({ const searchName = ref(); const searchState = ref('all'); const dialogUpgradeRef = ref(); +const dialogCommitRef = ref(); const dialogPortJumpRef = ref(); const opRef = ref(); const includeAppStore = ref(true); @@ -715,6 +718,15 @@ const buttons = [ return checkStatus('restart', row); }, }, + { + label: i18n.global.t('container.makeImage'), + click: (row: Container.ContainerInfo) => { + dialogCommitRef.value!.acceptParams({ containerID: row.containerID, containerName: row.name }); + }, + disabled: (row: any) => { + return checkStatus('commit', row); + }, + }, { label: i18n.global.t('container.kill'), click: (row: Container.ContainerInfo) => {