From 379b171f0a4a54ca10a241560e229ac1cf04fd18 Mon Sep 17 00:00:00 2001 From: ssongliu <73214554+ssongliu@users.noreply.github.com> Date: Fri, 28 Apr 2023 22:46:20 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3=E5=AE=B9=E5=99=A8?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E6=89=B9=E9=87=8F=E7=AB=AF=E5=8F=A3=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5=E7=9A=84=E9=97=AE=E9=A2=98=20(#830)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/service/container.go | 85 +++++++++++++------ backend/constant/errs.go | 1 + backend/i18n/lang/en.yaml | 1 + backend/i18n/lang/zh.yaml | 1 + .../container/container/create/index.vue | 2 +- 5 files changed, 61 insertions(+), 29 deletions(-) diff --git a/backend/app/service/container.go b/backend/app/service/container.go index 0cebe42ea..26a9e128f 100644 --- a/backend/app/service/container.go +++ b/backend/app/service/container.go @@ -166,35 +166,27 @@ func (u *ContainerService) Inspect(req dto.InspectReq) (string, error) { } func (u *ContainerService) ContainerCreate(req dto.ContainerCreate) error { - if len(req.ExposedPorts) != 0 { - for _, port := range req.ExposedPorts { - if strings.Contains(port.HostPort, "-") { - portStart, _ := strconv.Atoi(strings.Split(port.HostPort, "-")[0]) - portEnd, _ := strconv.Atoi(strings.Split(port.HostPort, "-")[1]) - for i := portStart; i <= portEnd; i++ { - if common.ScanPort(i) { - return buserr.WithDetail(constant.ErrPortInUsed, i, nil) - } - } - } else { - portItem, _ := strconv.Atoi(port.HostPort) - if common.ScanPort(portItem) { - return buserr.WithDetail(constant.ErrPortInUsed, portItem, nil) - } - } - } + portMap, err := checkPortStats(req.ExposedPorts) + if err != nil { + return err } client, err := docker.NewDockerClient() if err != nil { return err } + + exposeds := make(nat.PortSet) + for port := range portMap { + exposeds[port] = struct{}{} + } config := &container.Config{ - Image: req.Image, - Cmd: req.Cmd, - Env: req.Env, - Labels: stringsToMap(req.Labels), - Tty: true, - OpenStdin: true, + Image: req.Image, + Cmd: req.Cmd, + Env: req.Env, + Labels: stringsToMap(req.Labels), + Tty: true, + OpenStdin: true, + ExposedPorts: exposeds, } hostConf := &container.HostConfig{ AutoRemove: req.AutoRemove, @@ -211,11 +203,7 @@ func (u *ContainerService) ContainerCreate(req dto.ContainerCreate) error { hostConf.Memory = req.Memory } if len(req.ExposedPorts) != 0 { - hostConf.PortBindings = make(nat.PortMap) - for _, port := range req.ExposedPorts { - bindItem := nat.PortBinding{HostPort: port.HostPort, HostIP: port.HostIP} - hostConf.PortBindings[nat.Port(fmt.Sprintf("%s/%s", port.ContainerPort, port.Protocol))] = []nat.PortBinding{bindItem} - } + hostConf.PortBindings = portMap } if len(req.Volumes) != 0 { config.Volumes = make(map[string]struct{}) @@ -423,3 +411,44 @@ func loadCpuAndMem(client *client.Client, container string) (float64, float64) { MemPercent := calculateMemPercentUnix(stats.MemoryStats) return CPUPercent, MemPercent } + +func checkPortStats(ports []dto.PortHelper) (nat.PortMap, error) { + portMap := make(nat.PortMap) + if len(ports) == 0 { + return portMap, nil + } + for _, port := range ports { + if strings.Contains(port.HostPort, "-") { + if !strings.Contains(port.ContainerPort, "-") { + return portMap, buserr.New(constant.ErrPortRules) + } + hostStart, _ := strconv.Atoi(strings.Split(port.HostPort, "-")[0]) + hostEnd, _ := strconv.Atoi(strings.Split(port.HostPort, "-")[1]) + containerStart, _ := strconv.Atoi(strings.Split(port.ContainerPort, "-")[0]) + containerEnd, _ := strconv.Atoi(strings.Split(port.ContainerPort, "-")[1]) + if (hostEnd-hostStart) <= 0 || (containerEnd-containerStart) <= 0 { + return portMap, buserr.New(constant.ErrPortRules) + } + if (containerEnd - containerStart) != (hostEnd - hostStart) { + return portMap, buserr.New(constant.ErrPortRules) + } + for i := 0; i <= hostEnd-hostStart; i++ { + bindItem := nat.PortBinding{HostPort: strconv.Itoa(hostStart + i), HostIP: port.HostIP} + portMap[nat.Port(fmt.Sprintf("%d/%s", containerStart+i, port.Protocol))] = []nat.PortBinding{bindItem} + } + for i := hostStart; i <= hostEnd; i++ { + if common.ScanPort(i) { + return portMap, buserr.WithDetail(constant.ErrPortInUsed, i, nil) + } + } + } else { + portItem, _ := strconv.Atoi(port.HostPort) + if common.ScanPort(portItem) { + return portMap, buserr.WithDetail(constant.ErrPortInUsed, portItem, nil) + } + bindItem := nat.PortBinding{HostPort: strconv.Itoa(portItem), HostIP: port.HostIP} + portMap[nat.Port(fmt.Sprintf("%s/%s", port.ContainerPort, port.Protocol))] = []nat.PortBinding{bindItem} + } + } + return portMap, nil +} diff --git a/backend/constant/errs.go b/backend/constant/errs.go index b78381e11..a7f6aee10 100644 --- a/backend/constant/errs.go +++ b/backend/constant/errs.go @@ -106,6 +106,7 @@ var ( var ( ErrInUsed = "ErrInUsed" ErrObjectInUsed = "ErrObjectInUsed" + ErrPortRules = "ErrPortRules" ) // runtime diff --git a/backend/i18n/lang/en.yaml b/backend/i18n/lang/en.yaml index dd497fbf7..175fee311 100644 --- a/backend/i18n/lang/en.yaml +++ b/backend/i18n/lang/en.yaml @@ -63,6 +63,7 @@ ErrTypeOfRedis: "The recovery file type does not match the current persistence m #container ErrInUsed: "{{ .detail }} is in use and cannot be deleted" ErrObjectInUsed: "This object is in use and cannot be deleted" +ErrPortRules: "Invalid port specification" #runtime ErrDirNotFound: "The build folder does not exist! Please check file integrity!" diff --git a/backend/i18n/lang/zh.yaml b/backend/i18n/lang/zh.yaml index 45036643a..d4982b536 100644 --- a/backend/i18n/lang/zh.yaml +++ b/backend/i18n/lang/zh.yaml @@ -63,6 +63,7 @@ ErrTypeOfRedis: "恢复文件类型与当前持久化方式不符,请修改后 #container ErrInUsed: "{{ .detail }} 正被使用,无法删除" ErrObjectInUsed: "该对象正被使用,无法删除" +ErrPortRules: "无效的端口规格" #runtime ErrDirNotFound: "build 文件夹不存在!请检查文件完整性!" diff --git a/frontend/src/views/container/container/create/index.vue b/frontend/src/views/container/container/create/index.vue index 3cefcda64..51cdf4e3d 100644 --- a/frontend/src/views/container/container/create/index.vue +++ b/frontend/src/views/container/container/create/index.vue @@ -364,7 +364,7 @@ const onSubmit = async (formEl: FormInstance | undefined) => { }); }; -const checkPortValid = async () => { +const checkPortValid = () => { if (form.exposedPorts.length === 0) { return true; }