Fix the Ports mappings in edit view and refactor container editing and creation flow
- Display ports with the protocol in the edit view. - Rearrange container creation steps for better flow: stopping the old container is now the first step. - Remove unused code related to ExposedPorts. - Rename ExposedPort to ContainerPort for better clarity in the PortMapping struct. - Integrate port parsing directly into the YAML-to-CmdParams conversion.
- commit
- 220ba47f6e3ab74b403ec4bf8bbf2e8943d5b480
- author
- bnema · · 2023-10-09 18:17 UTC
- parent
- 188621f
- signature
- unsigned
3 files · +38 -44
M internal/httpserve/handler/editcontainer.go +9 -20
| @@ -51,25 +51,14 @@ func ContainerManagerEditGET(c echo.Context, a *app.App) error { | |||
| 51 | 51 | networkNames = append(networkNames, networkName) | |
| 52 | 52 | } | |
| 53 | 53 | ||
| 54 | - | // Prepare Ports (PortBindings and ExposedPorts) | |
| 54 | + | // Prepare Ports | |
| 55 | 55 | portMappings := make([]string, 0) | |
| 56 | 56 | for port, bindings := range containerInfo.HostConfig.PortBindings { | |
| 57 | 57 | for _, binding := range bindings { | |
| 58 | - | portMappings = append(portMappings, fmt.Sprintf("%s:%s", binding.HostPort, port.Port())) | |
| 58 | + | portMappings = append(portMappings, fmt.Sprintf("%s:%s/%s", binding.HostPort, port.Port(), port.Proto())) | |
| 59 | 59 | } | |
| 60 | 60 | } | |
| 61 | 61 | ||
| 62 | - | exposedPorts := make([]string, 0) | |
| 63 | - | for port := range containerInfo.Config.ExposedPorts { | |
| 64 | - | exposedPorts = append(exposedPorts, port.Port()) | |
| 65 | - | } | |
| 66 | - | ||
| 67 | - | // Prepare Ports while using the containerInfo.Config.ExposedPorts | |
| 68 | - | ||
| 69 | - | for port := range containerInfo.Config.ExposedPorts { | |
| 70 | - | fmt.Println(port) | |
| 71 | - | } | |
| 72 | - | ||
| 73 | 62 | // Prepare Volumes (Mounts) | |
| 74 | 63 | volumeMappings := make([]string, 0) | |
| 75 | 64 | for _, mount := range containerInfo.Mounts { | |
| @@ -187,21 +176,21 @@ func ContainerManagerEditPOST(c echo.Context, a *app.App) error { | |||
| 187 | 176 | tq.NewContainerName = cmdParams.ContainerName | |
| 188 | 177 | tq.TempContainerName = fmt.Sprintf("%s-temp", tq.NewContainerName) | |
| 189 | 178 | ||
| 190 | - | // 1. Create a new container with the new configuration with a temporary name if old container name and new container name are different | |
| 191 | 179 | cmdParams.ContainerName = tq.TempContainerName | |
| 192 | 180 | ||
| 181 | + | // 1. Stop the old container | |
| 182 | + | tq.Add(StopOldContainerStep(tq), StartOldContainerRollback(tq)) | |
| 183 | + | ||
| 184 | + | // 2. Create the new container | |
| 193 | 185 | tq.Add(CreateNewContainerStep(tq, cmdParams), RemoveNewContainerRollback(tq)) | |
| 194 | 186 | ||
| 195 | - | // 2. Start the new container | |
| 187 | + | // 3. Start the new container | |
| 196 | 188 | tq.Add(StartNewContainerStep(tq), StopNewContainerRollback(tq)) | |
| 197 | 189 | ||
| 198 | - | // 3. Stop the old container | |
| 199 | - | tq.Add(StopOldContainerStep(tq), StartOldContainerRollback(tq)) | |
| 200 | - | ||
| 201 | - | // 4. Remove the old container | |
| 190 | + | // 4. Rename the new container to the original name | |
| 202 | 191 | tq.Add(RemoveOldContainerStep(tq), nil) | |
| 203 | 192 | ||
| 204 | - | // 5. Rename the new container to the original name | |
| 193 | + | // 5. Remove the old container | |
| 205 | 194 | tq.Add(RenameNewContainerStep(tq), RenameNewContainerRollback(tq)) | |
| 206 | 195 | ||
| 207 | 196 | err = tq.Execute() | |
| @@ -51,25 +51,14 @@ func ContainerManagerEditGET(c echo.Context, a *app.App) error { | |||||
| 51 | networkNames = append(networkNames, networkName) | 51 | networkNames = append(networkNames, networkName) | ||
| 52 | } | 52 | } | ||
| 53 | 53 | ||||
| 54 | - | // Prepare Ports (PortBindings and ExposedPorts) | 54 | + | // Prepare Ports |
| 55 | portMappings := make([]string, 0) | 55 | portMappings := make([]string, 0) | ||
| 56 | for port, bindings := range containerInfo.HostConfig.PortBindings { | 56 | for port, bindings := range containerInfo.HostConfig.PortBindings { | ||
| 57 | for _, binding := range bindings { | 57 | for _, binding := range bindings { | ||
| 58 | - | portMappings = append(portMappings, fmt.Sprintf("%s:%s", binding.HostPort, port.Port())) | 58 | + | portMappings = append(portMappings, fmt.Sprintf("%s:%s/%s", binding.HostPort, port.Port(), port.Proto())) |
| 59 | } | 59 | } | ||
| 60 | } | 60 | } | ||
| 61 | 61 | ||||
| 62 | - | exposedPorts := make([]string, 0) | |||
| 63 | - | for port := range containerInfo.Config.ExposedPorts { | |||
| 64 | - | exposedPorts = append(exposedPorts, port.Port()) | |||
| 65 | - | } | |||
| 66 | - | ||||
| 67 | - | // Prepare Ports while using the containerInfo.Config.ExposedPorts | |||
| 68 | - | ||||
| 69 | - | for port := range containerInfo.Config.ExposedPorts { | |||
| 70 | - | fmt.Println(port) | |||
| 71 | - | } | |||
| 72 | - | ||||
| 73 | // Prepare Volumes (Mounts) | 62 | // Prepare Volumes (Mounts) | ||
| 74 | volumeMappings := make([]string, 0) | 63 | volumeMappings := make([]string, 0) | ||
| 75 | for _, mount := range containerInfo.Mounts { | 64 | for _, mount := range containerInfo.Mounts { | ||
| @@ -187,21 +176,21 @@ func ContainerManagerEditPOST(c echo.Context, a *app.App) error { | |||||
| 187 | tq.NewContainerName = cmdParams.ContainerName | 176 | tq.NewContainerName = cmdParams.ContainerName | ||
| 188 | tq.TempContainerName = fmt.Sprintf("%s-temp", tq.NewContainerName) | 177 | tq.TempContainerName = fmt.Sprintf("%s-temp", tq.NewContainerName) | ||
| 189 | 178 | ||||
| 190 | - | // 1. Create a new container with the new configuration with a temporary name if old container name and new container name are different | |||
| 191 | cmdParams.ContainerName = tq.TempContainerName | 179 | cmdParams.ContainerName = tq.TempContainerName | ||
| 192 | 180 | ||||
| 181 | + | // 1. Stop the old container | |||
| 182 | + | tq.Add(StopOldContainerStep(tq), StartOldContainerRollback(tq)) | |||
| 183 | + | ||||
| 184 | + | // 2. Create the new container | |||
| 193 | tq.Add(CreateNewContainerStep(tq, cmdParams), RemoveNewContainerRollback(tq)) | 185 | tq.Add(CreateNewContainerStep(tq, cmdParams), RemoveNewContainerRollback(tq)) | ||
| 194 | 186 | ||||
| 195 | - | // 2. Start the new container | 187 | + | // 3. Start the new container |
| 196 | tq.Add(StartNewContainerStep(tq), StopNewContainerRollback(tq)) | 188 | tq.Add(StartNewContainerStep(tq), StopNewContainerRollback(tq)) | ||
| 197 | 189 | ||||
| 198 | - | // 3. Stop the old container | 190 | + | // 4. Rename the new container to the original name |
| 199 | - | tq.Add(StopOldContainerStep(tq), StartOldContainerRollback(tq)) | |||
| 200 | - | ||||
| 201 | - | // 4. Remove the old container | |||
| 202 | tq.Add(RemoveOldContainerStep(tq), nil) | 191 | tq.Add(RemoveOldContainerStep(tq), nil) | ||
| 203 | 192 | ||||
| 204 | - | // 5. Rename the new container to the original name | 193 | + | // 5. Remove the old container |
| 205 | tq.Add(RenameNewContainerStep(tq), RenameNewContainerRollback(tq)) | 194 | tq.Add(RenameNewContainerStep(tq), RenameNewContainerRollback(tq)) | ||
| 206 | 195 | ||||
| 207 | err = tq.Execute() | 196 | err = tq.Execute() | ||
M internal/templates/render/cmdparams.go +10 -4
| @@ -34,7 +34,7 @@ func FromInputsToCmdParams(inputs map[string]string, a *app.App) (docker.Contain | |||
| 34 | 34 | } | |
| 35 | 35 | ||
| 36 | 36 | // Get the exposed port for traefik labels | |
| 37 | - | exposedPort := portMappings[0].ExposedPort | |
| 37 | + | exposedPort := portMappings[0].ContainerPort | |
| 38 | 38 | ||
| 39 | 39 | params := docker.ContainerCommandParams{ | |
| 40 | 40 | IsSSL: inputs["container_protocol"] == "https", | |
| @@ -80,9 +80,8 @@ type YAMLContainerParams struct { | |||
| 80 | 80 | Volumes []string `yaml:"Volumes"` | |
| 81 | 81 | Environment []string `yaml:"Environment"` | |
| 82 | 82 | Labels map[string]string `yaml:"Labels"` | |
| 83 | - | // Network is a slice of strings in the textarea | |
| 84 | - | Network []string `yaml:"Network"` | |
| 85 | - | Restart string `yaml:"Restart"` | |
| 83 | + | Network []string `yaml:"Network"` | |
| 84 | + | Restart string `yaml:"Restart"` | |
| 86 | 85 | } | |
| 87 | 86 | ||
| 88 | 87 | // FromYAMLStructToCmdParams converts a YAMLContainerParams struct to a ContainerCommandParams struct | |
| @@ -100,6 +99,12 @@ func FromYAMLStructToCmdParams(yamlParams YAMLContainerParams) (docker.Container | |||
| 100 | 99 | labels = append(labels, fmt.Sprintf("%s=%s", k, v)) | |
| 101 | 100 | } | |
| 102 | 101 | ||
| 102 | + | // Ports input parsing | |
| 103 | + | portMappings, err := docker.ParsePortsSpecs(yamlParams.Ports) | |
| 104 | + | if err != nil { | |
| 105 | + | return docker.ContainerCommandParams{}, err | |
| 106 | + | } | |
| 107 | + | ||
| 103 | 108 | // Convert the slice of strings to a comma separated string | |
| 104 | 109 | network := strings.Join(yamlParams.Network, ",") | |
| 105 | 110 | ||
| @@ -112,6 +117,7 @@ func FromYAMLStructToCmdParams(yamlParams YAMLContainerParams) (docker.Container | |||
| 112 | 117 | Labels: labels, | |
| 113 | 118 | Network: network, | |
| 114 | 119 | Restart: yamlParams.Restart, | |
| 120 | + | PortMappings: portMappings, | |
| 115 | 121 | } | |
| 116 | 122 | ||
| 117 | 123 | return params, nil | |
| @@ -34,7 +34,7 @@ func FromInputsToCmdParams(inputs map[string]string, a *app.App) (docker.Contain | |||||
| 34 | } | 34 | } | ||
| 35 | 35 | ||||
| 36 | // Get the exposed port for traefik labels | 36 | // Get the exposed port for traefik labels | ||
| 37 | - | exposedPort := portMappings[0].ExposedPort | 37 | + | exposedPort := portMappings[0].ContainerPort |
| 38 | 38 | ||||
| 39 | params := docker.ContainerCommandParams{ | 39 | params := docker.ContainerCommandParams{ | ||
| 40 | IsSSL: inputs["container_protocol"] == "https", | 40 | IsSSL: inputs["container_protocol"] == "https", | ||
| @@ -80,9 +80,8 @@ type YAMLContainerParams struct { | |||||
| 80 | Volumes []string `yaml:"Volumes"` | 80 | Volumes []string `yaml:"Volumes"` | ||
| 81 | Environment []string `yaml:"Environment"` | 81 | Environment []string `yaml:"Environment"` | ||
| 82 | Labels map[string]string `yaml:"Labels"` | 82 | Labels map[string]string `yaml:"Labels"` | ||
| 83 | - | // Network is a slice of strings in the textarea | 83 | + | Network []string `yaml:"Network"` |
| 84 | - | Network []string `yaml:"Network"` | 84 | + | Restart string `yaml:"Restart"` |
| 85 | - | Restart string `yaml:"Restart"` | |||
| 86 | } | 85 | } | ||
| 87 | 86 | ||||
| 88 | // FromYAMLStructToCmdParams converts a YAMLContainerParams struct to a ContainerCommandParams struct | 87 | // FromYAMLStructToCmdParams converts a YAMLContainerParams struct to a ContainerCommandParams struct | ||
| @@ -100,6 +99,12 @@ func FromYAMLStructToCmdParams(yamlParams YAMLContainerParams) (docker.Container | |||||
| 100 | labels = append(labels, fmt.Sprintf("%s=%s", k, v)) | 99 | labels = append(labels, fmt.Sprintf("%s=%s", k, v)) | ||
| 101 | } | 100 | } | ||
| 102 | 101 | ||||
| 102 | + | // Ports input parsing | |||
| 103 | + | portMappings, err := docker.ParsePortsSpecs(yamlParams.Ports) | |||
| 104 | + | if err != nil { | |||
| 105 | + | return docker.ContainerCommandParams{}, err | |||
| 106 | + | } | |||
| 107 | + | ||||
| 103 | // Convert the slice of strings to a comma separated string | 108 | // Convert the slice of strings to a comma separated string | ||
| 104 | network := strings.Join(yamlParams.Network, ",") | 109 | network := strings.Join(yamlParams.Network, ",") | ||
| 105 | 110 | ||||
| @@ -112,6 +117,7 @@ func FromYAMLStructToCmdParams(yamlParams YAMLContainerParams) (docker.Container | |||||
| 112 | Labels: labels, | 117 | Labels: labels, | ||
| 113 | Network: network, | 118 | Network: network, | ||
| 114 | Restart: yamlParams.Restart, | 119 | Restart: yamlParams.Restart, | ||
| 120 | + | PortMappings: portMappings, | |||
| 115 | } | 121 | } | ||
| 116 | 122 | ||||
| 117 | return params, nil | 123 | return params, nil | ||
M pkg/docker/containers.go +19 -20
| @@ -32,9 +32,9 @@ type ContainerCommandParams struct { | |||
| 32 | 32 | } | |
| 33 | 33 | ||
| 34 | 34 | type PortMapping struct { | |
| 35 | - | HostPort string | |
| 36 | - | ExposedPort string | |
| 37 | - | Protocol string | |
| 35 | + | HostPort string | |
| 36 | + | ContainerPort string | |
| 37 | + | Protocol string | |
| 38 | 38 | } | |
| 39 | 39 | ||
| 40 | 40 | // ParsePortsSpecs receives a slice of strings in the format "hostPort:containerPort/Protocol" and returns a slice of PortMapping structs | |
| @@ -47,28 +47,28 @@ func ParsePortsSpecs(portsSpecs []string) ([]PortMapping, error) { | |||
| 47 | 47 | return nil, fmt.Errorf("invalid port specification: %s. Format should be hostPort:containerPort[/Protocol]", portSpec) | |
| 48 | 48 | } | |
| 49 | 49 | ||
| 50 | - | // Validate hostPort and exposedPort are numbers | |
| 50 | + | // Validate hostPort and containerPort | |
| 51 | 51 | hostPort := parts[0] | |
| 52 | 52 | if _, err := strconv.Atoi(hostPort); err != nil { | |
| 53 | 53 | return nil, fmt.Errorf("invalid host port: %s. Must be a number", hostPort) | |
| 54 | 54 | } | |
| 55 | 55 | ||
| 56 | - | exposedParts := strings.Split(parts[1], "/") | |
| 57 | - | exposedPort := exposedParts[0] | |
| 58 | - | if _, err := strconv.Atoi(exposedPort); err != nil { | |
| 59 | - | return nil, fmt.Errorf("invalid exposed port: %s. Must be a number", exposedPort) | |
| 56 | + | containerParts := strings.Split(parts[1], "/") | |
| 57 | + | containerPort := containerParts[0] | |
| 58 | + | if _, err := strconv.Atoi(containerPort); err != nil { | |
| 59 | + | return nil, fmt.Errorf("invalid exposed port: %s. Must be a number", containerPort) | |
| 60 | 60 | } | |
| 61 | 61 | ||
| 62 | 62 | // Default protocol is tcp | |
| 63 | 63 | protocol := "tcp" | |
| 64 | - | if len(exposedParts) > 1 { | |
| 65 | - | protocol = exposedParts[1] | |
| 64 | + | if len(containerParts) > 1 { | |
| 65 | + | protocol = containerParts[1] | |
| 66 | 66 | } | |
| 67 | 67 | ||
| 68 | 68 | portMappings = append(portMappings, PortMapping{ | |
| 69 | - | HostPort: hostPort, | |
| 70 | - | ExposedPort: exposedPort, | |
| 71 | - | Protocol: protocol, | |
| 69 | + | HostPort: hostPort, | |
| 70 | + | ContainerPort: containerPort, | |
| 71 | + | Protocol: protocol, | |
| 72 | 72 | }) | |
| 73 | 73 | } | |
| 74 | 74 | ||
| @@ -77,12 +77,11 @@ func ParsePortsSpecs(portsSpecs []string) ([]PortMapping, error) { | |||
| 77 | 77 | ||
| 78 | 78 | func ContainerCommandParamsToConfig(cmdParams ContainerCommandParams) (*container.Config, error) { | |
| 79 | 79 | return &container.Config{ | |
| 80 | - | Image: cmdParams.ImageName, | |
| 81 | - | Hostname: cmdParams.ContainerHost, | |
| 82 | - | ExposedPorts: map[nat.Port]struct{}{}, | |
| 83 | - | Env: cmdParams.Environment, | |
| 84 | - | Labels: map[string]string{}, | |
| 85 | - | Volumes: map[string]struct{}{}, | |
| 80 | + | Image: cmdParams.ImageName, | |
| 81 | + | Hostname: cmdParams.ContainerHost, | |
| 82 | + | Env: cmdParams.Environment, | |
| 83 | + | Labels: map[string]string{}, | |
| 84 | + | Volumes: map[string]struct{}{}, | |
| 86 | 85 | }, nil | |
| 87 | 86 | } | |
| 88 | 87 | ||
| @@ -201,7 +200,7 @@ func CreateContainer(cmdParams ContainerCommandParams) (string, error) { | |||
| 201 | 200 | portBindings := nat.PortMap{} | |
| 202 | 201 | for _, portMapping := range cmdParams.PortMappings { | |
| 203 | 202 | // Prepare exposed port | |
| 204 | - | exposedPort := nat.Port(portMapping.ExposedPort + "/" + portMapping.Protocol) | |
| 203 | + | exposedPort := nat.Port(portMapping.ContainerPort + "/" + portMapping.Protocol) | |
| 205 | 204 | portBindings[exposedPort] = []nat.PortBinding{ | |
| 206 | 205 | { | |
| 207 | 206 | HostIP: "0.0.0.0", | |
| @@ -32,9 +32,9 @@ type ContainerCommandParams struct { | |||||
| 32 | } | 32 | } | ||
| 33 | 33 | ||||
| 34 | type PortMapping struct { | 34 | type PortMapping struct { | ||
| 35 | - | HostPort string | 35 | + | HostPort string |
| 36 | - | ExposedPort string | 36 | + | ContainerPort string |
| 37 | - | Protocol string | 37 | + | Protocol string |
| 38 | } | 38 | } | ||
| 39 | 39 | ||||
| 40 | // ParsePortsSpecs receives a slice of strings in the format "hostPort:containerPort/Protocol" and returns a slice of PortMapping structs | 40 | // ParsePortsSpecs receives a slice of strings in the format "hostPort:containerPort/Protocol" and returns a slice of PortMapping structs | ||
| @@ -47,28 +47,28 @@ func ParsePortsSpecs(portsSpecs []string) ([]PortMapping, error) { | |||||
| 47 | return nil, fmt.Errorf("invalid port specification: %s. Format should be hostPort:containerPort[/Protocol]", portSpec) | 47 | return nil, fmt.Errorf("invalid port specification: %s. Format should be hostPort:containerPort[/Protocol]", portSpec) | ||
| 48 | } | 48 | } | ||
| 49 | 49 | ||||
| 50 | - | // Validate hostPort and exposedPort are numbers | 50 | + | // Validate hostPort and containerPort |
| 51 | hostPort := parts[0] | 51 | hostPort := parts[0] | ||
| 52 | if _, err := strconv.Atoi(hostPort); err != nil { | 52 | if _, err := strconv.Atoi(hostPort); err != nil { | ||
| 53 | return nil, fmt.Errorf("invalid host port: %s. Must be a number", hostPort) | 53 | return nil, fmt.Errorf("invalid host port: %s. Must be a number", hostPort) | ||
| 54 | } | 54 | } | ||
| 55 | 55 | ||||
| 56 | - | exposedParts := strings.Split(parts[1], "/") | 56 | + | containerParts := strings.Split(parts[1], "/") |
| 57 | - | exposedPort := exposedParts[0] | 57 | + | containerPort := containerParts[0] |
| 58 | - | if _, err := strconv.Atoi(exposedPort); err != nil { | 58 | + | if _, err := strconv.Atoi(containerPort); err != nil { |
| 59 | - | return nil, fmt.Errorf("invalid exposed port: %s. Must be a number", exposedPort) | 59 | + | return nil, fmt.Errorf("invalid exposed port: %s. Must be a number", containerPort) |
| 60 | } | 60 | } | ||
| 61 | 61 | ||||
| 62 | // Default protocol is tcp | 62 | // Default protocol is tcp | ||
| 63 | protocol := "tcp" | 63 | protocol := "tcp" | ||
| 64 | - | if len(exposedParts) > 1 { | 64 | + | if len(containerParts) > 1 { |
| 65 | - | protocol = exposedParts[1] | 65 | + | protocol = containerParts[1] |
| 66 | } | 66 | } | ||
| 67 | 67 | ||||
| 68 | portMappings = append(portMappings, PortMapping{ | 68 | portMappings = append(portMappings, PortMapping{ | ||
| 69 | - | HostPort: hostPort, | 69 | + | HostPort: hostPort, |
| 70 | - | ExposedPort: exposedPort, | 70 | + | ContainerPort: containerPort, |
| 71 | - | Protocol: protocol, | 71 | + | Protocol: protocol, |
| 72 | }) | 72 | }) | ||
| 73 | } | 73 | } | ||
| 74 | 74 | ||||
| @@ -77,12 +77,11 @@ func ParsePortsSpecs(portsSpecs []string) ([]PortMapping, error) { | |||||
| 77 | 77 | ||||
| 78 | func ContainerCommandParamsToConfig(cmdParams ContainerCommandParams) (*container.Config, error) { | 78 | func ContainerCommandParamsToConfig(cmdParams ContainerCommandParams) (*container.Config, error) { | ||
| 79 | return &container.Config{ | 79 | return &container.Config{ | ||
| 80 | - | Image: cmdParams.ImageName, | 80 | + | Image: cmdParams.ImageName, |
| 81 | - | Hostname: cmdParams.ContainerHost, | 81 | + | Hostname: cmdParams.ContainerHost, |
| 82 | - | ExposedPorts: map[nat.Port]struct{}{}, | 82 | + | Env: cmdParams.Environment, |
| 83 | - | Env: cmdParams.Environment, | 83 | + | Labels: map[string]string{}, |
| 84 | - | Labels: map[string]string{}, | 84 | + | Volumes: map[string]struct{}{}, |
| 85 | - | Volumes: map[string]struct{}{}, | |||
| 86 | }, nil | 85 | }, nil | ||
| 87 | } | 86 | } | ||
| 88 | 87 | ||||
| @@ -201,7 +200,7 @@ func CreateContainer(cmdParams ContainerCommandParams) (string, error) { | |||||
| 201 | portBindings := nat.PortMap{} | 200 | portBindings := nat.PortMap{} | ||
| 202 | for _, portMapping := range cmdParams.PortMappings { | 201 | for _, portMapping := range cmdParams.PortMappings { | ||
| 203 | // Prepare exposed port | 202 | // Prepare exposed port | ||
| 204 | - | exposedPort := nat.Port(portMapping.ExposedPort + "/" + portMapping.Protocol) | 203 | + | exposedPort := nat.Port(portMapping.ContainerPort + "/" + portMapping.Protocol) |
| 205 | portBindings[exposedPort] = []nat.PortBinding{ | 204 | portBindings[exposedPort] = []nat.PortBinding{ | ||
| 206 | { | 205 | { | ||
| 207 | HostIP: "0.0.0.0", | 206 | HostIP: "0.0.0.0", | ||