github.com/shiroyuki/docker@v1.9.0/integration-cli/docker_cli_port_test.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "net" 6 "regexp" 7 "sort" 8 "strings" 9 10 "github.com/go-check/check" 11 ) 12 13 func (s *DockerSuite) TestPortList(c *check.C) { 14 testRequires(c, DaemonIsLinux) 15 // one port 16 out, _ := dockerCmd(c, "run", "-d", "-p", "9876:80", "busybox", "top") 17 firstID := strings.TrimSpace(out) 18 19 out, _ = dockerCmd(c, "port", firstID, "80") 20 21 if !assertPortList(c, out, []string{"0.0.0.0:9876"}) { 22 c.Error("Port list is not correct") 23 } 24 25 out, _ = dockerCmd(c, "port", firstID) 26 27 if !assertPortList(c, out, []string{"80/tcp -> 0.0.0.0:9876"}) { 28 c.Error("Port list is not correct") 29 } 30 dockerCmd(c, "rm", "-f", firstID) 31 32 // three port 33 out, _ = dockerCmd(c, "run", "-d", 34 "-p", "9876:80", 35 "-p", "9877:81", 36 "-p", "9878:82", 37 "busybox", "top") 38 ID := strings.TrimSpace(out) 39 40 out, _ = dockerCmd(c, "port", ID, "80") 41 42 if !assertPortList(c, out, []string{"0.0.0.0:9876"}) { 43 c.Error("Port list is not correct") 44 } 45 46 out, _ = dockerCmd(c, "port", ID) 47 48 if !assertPortList(c, out, []string{ 49 "80/tcp -> 0.0.0.0:9876", 50 "81/tcp -> 0.0.0.0:9877", 51 "82/tcp -> 0.0.0.0:9878"}) { 52 c.Error("Port list is not correct") 53 } 54 dockerCmd(c, "rm", "-f", ID) 55 56 // more and one port mapped to the same container port 57 out, _ = dockerCmd(c, "run", "-d", 58 "-p", "9876:80", 59 "-p", "9999:80", 60 "-p", "9877:81", 61 "-p", "9878:82", 62 "busybox", "top") 63 ID = strings.TrimSpace(out) 64 65 out, _ = dockerCmd(c, "port", ID, "80") 66 67 if !assertPortList(c, out, []string{"0.0.0.0:9876", "0.0.0.0:9999"}) { 68 c.Error("Port list is not correct") 69 } 70 71 out, _ = dockerCmd(c, "port", ID) 72 73 if !assertPortList(c, out, []string{ 74 "80/tcp -> 0.0.0.0:9876", 75 "80/tcp -> 0.0.0.0:9999", 76 "81/tcp -> 0.0.0.0:9877", 77 "82/tcp -> 0.0.0.0:9878"}) { 78 c.Error("Port list is not correct\n", out) 79 } 80 dockerCmd(c, "rm", "-f", ID) 81 82 testRange := func() { 83 // host port ranges used 84 IDs := make([]string, 3) 85 for i := 0; i < 3; i++ { 86 out, _ = dockerCmd(c, "run", "-d", 87 "-p", "9090-9092:80", 88 "busybox", "top") 89 IDs[i] = strings.TrimSpace(out) 90 91 out, _ = dockerCmd(c, "port", IDs[i]) 92 93 if !assertPortList(c, out, []string{ 94 fmt.Sprintf("80/tcp -> 0.0.0.0:%d", 9090+i)}) { 95 c.Error("Port list is not correct\n", out) 96 } 97 } 98 99 // test port range exhaustion 100 out, _, err := dockerCmdWithError("run", "-d", 101 "-p", "9090-9092:80", 102 "busybox", "top") 103 if err == nil { 104 c.Errorf("Exhausted port range did not return an error. Out: %s", out) 105 } 106 107 for i := 0; i < 3; i++ { 108 dockerCmd(c, "rm", "-f", IDs[i]) 109 } 110 } 111 testRange() 112 // Verify we ran re-use port ranges after they are no longer in use. 113 testRange() 114 115 // test invalid port ranges 116 for _, invalidRange := range []string{"9090-9089:80", "9090-:80", "-9090:80"} { 117 out, _, err := dockerCmdWithError("run", "-d", 118 "-p", invalidRange, 119 "busybox", "top") 120 if err == nil { 121 c.Errorf("Port range should have returned an error. Out: %s", out) 122 } 123 } 124 125 // test host range:container range spec. 126 out, _ = dockerCmd(c, "run", "-d", 127 "-p", "9800-9803:80-83", 128 "busybox", "top") 129 ID = strings.TrimSpace(out) 130 131 out, _ = dockerCmd(c, "port", ID) 132 133 if !assertPortList(c, out, []string{ 134 "80/tcp -> 0.0.0.0:9800", 135 "81/tcp -> 0.0.0.0:9801", 136 "82/tcp -> 0.0.0.0:9802", 137 "83/tcp -> 0.0.0.0:9803"}) { 138 c.Error("Port list is not correct\n", out) 139 } 140 dockerCmd(c, "rm", "-f", ID) 141 142 // test mixing protocols in same port range 143 out, _ = dockerCmd(c, "run", "-d", 144 "-p", "8000-8080:80", 145 "-p", "8000-8080:80/udp", 146 "busybox", "top") 147 ID = strings.TrimSpace(out) 148 149 out, _ = dockerCmd(c, "port", ID) 150 151 if !assertPortList(c, out, []string{ 152 "80/tcp -> 0.0.0.0:8000", 153 "80/udp -> 0.0.0.0:8000"}) { 154 c.Error("Port list is not correct\n", out) 155 } 156 dockerCmd(c, "rm", "-f", ID) 157 } 158 159 func assertPortList(c *check.C, out string, expected []string) bool { 160 //lines := strings.Split(out, "\n") 161 lines := strings.Split(strings.Trim(out, "\n "), "\n") 162 if len(lines) != len(expected) { 163 c.Errorf("different size lists %s, %d, %d", out, len(lines), len(expected)) 164 return false 165 } 166 sort.Strings(lines) 167 sort.Strings(expected) 168 169 for i := 0; i < len(expected); i++ { 170 if lines[i] != expected[i] { 171 c.Error("|" + lines[i] + "!=" + expected[i] + "|") 172 return false 173 } 174 } 175 176 return true 177 } 178 179 func stopRemoveContainer(id string, c *check.C) { 180 dockerCmd(c, "rm", "-f", id) 181 } 182 183 func (s *DockerSuite) TestUnpublishedPortsInPsOutput(c *check.C) { 184 testRequires(c, DaemonIsLinux) 185 // Run busybox with command line expose (equivalent to EXPOSE in image's Dockerfile) for the following ports 186 port1 := 80 187 port2 := 443 188 expose1 := fmt.Sprintf("--expose=%d", port1) 189 expose2 := fmt.Sprintf("--expose=%d", port2) 190 dockerCmd(c, "run", "-d", expose1, expose2, "busybox", "sleep", "5") 191 192 // Check docker ps o/p for last created container reports the unpublished ports 193 unpPort1 := fmt.Sprintf("%d/tcp", port1) 194 unpPort2 := fmt.Sprintf("%d/tcp", port2) 195 out, _ := dockerCmd(c, "ps", "-n=1") 196 if !strings.Contains(out, unpPort1) || !strings.Contains(out, unpPort2) { 197 c.Errorf("Missing unpublished ports(s) (%s, %s) in docker ps output: %s", unpPort1, unpPort2, out) 198 } 199 200 // Run the container forcing to publish the exposed ports 201 dockerCmd(c, "run", "-d", "-P", expose1, expose2, "busybox", "sleep", "5") 202 203 // Check docker ps o/p for last created container reports the exposed ports in the port bindings 204 expBndRegx1 := regexp.MustCompile(`0.0.0.0:\d\d\d\d\d->` + unpPort1) 205 expBndRegx2 := regexp.MustCompile(`0.0.0.0:\d\d\d\d\d->` + unpPort2) 206 out, _ = dockerCmd(c, "ps", "-n=1") 207 if !expBndRegx1.MatchString(out) || !expBndRegx2.MatchString(out) { 208 c.Errorf("Cannot find expected port binding ports(s) (0.0.0.0:xxxxx->%s, 0.0.0.0:xxxxx->%s) in docker ps output:\n%s", 209 unpPort1, unpPort2, out) 210 } 211 212 // Run the container specifying explicit port bindings for the exposed ports 213 offset := 10000 214 pFlag1 := fmt.Sprintf("%d:%d", offset+port1, port1) 215 pFlag2 := fmt.Sprintf("%d:%d", offset+port2, port2) 216 out, _ = dockerCmd(c, "run", "-d", "-p", pFlag1, "-p", pFlag2, expose1, expose2, "busybox", "sleep", "5") 217 id := strings.TrimSpace(out) 218 219 // Check docker ps o/p for last created container reports the specified port mappings 220 expBnd1 := fmt.Sprintf("0.0.0.0:%d->%s", offset+port1, unpPort1) 221 expBnd2 := fmt.Sprintf("0.0.0.0:%d->%s", offset+port2, unpPort2) 222 out, _ = dockerCmd(c, "ps", "-n=1") 223 if !strings.Contains(out, expBnd1) || !strings.Contains(out, expBnd2) { 224 c.Errorf("Cannot find expected port binding(s) (%s, %s) in docker ps output: %s", expBnd1, expBnd2, out) 225 } 226 // Remove container now otherwise it will interfeer with next test 227 stopRemoveContainer(id, c) 228 229 // Run the container with explicit port bindings and no exposed ports 230 out, _ = dockerCmd(c, "run", "-d", "-p", pFlag1, "-p", pFlag2, "busybox", "sleep", "5") 231 id = strings.TrimSpace(out) 232 233 // Check docker ps o/p for last created container reports the specified port mappings 234 out, _ = dockerCmd(c, "ps", "-n=1") 235 if !strings.Contains(out, expBnd1) || !strings.Contains(out, expBnd2) { 236 c.Errorf("Cannot find expected port binding(s) (%s, %s) in docker ps output: %s", expBnd1, expBnd2, out) 237 } 238 // Remove container now otherwise it will interfeer with next test 239 stopRemoveContainer(id, c) 240 241 // Run the container with one unpublished exposed port and one explicit port binding 242 dockerCmd(c, "run", "-d", expose1, "-p", pFlag2, "busybox", "sleep", "5") 243 244 // Check docker ps o/p for last created container reports the specified unpublished port and port mapping 245 out, _ = dockerCmd(c, "ps", "-n=1") 246 if !strings.Contains(out, unpPort1) || !strings.Contains(out, expBnd2) { 247 c.Errorf("Missing unpublished ports or port binding (%s, %s) in docker ps output: %s", unpPort1, expBnd2, out) 248 } 249 } 250 251 func (s *DockerSuite) TestPortHostBinding(c *check.C) { 252 testRequires(c, DaemonIsLinux, NotUserNamespace) 253 out, _ := dockerCmd(c, "run", "-d", "-p", "9876:80", "busybox", 254 "nc", "-l", "-p", "80") 255 firstID := strings.TrimSpace(out) 256 257 out, _ = dockerCmd(c, "port", firstID, "80") 258 259 if !assertPortList(c, out, []string{"0.0.0.0:9876"}) { 260 c.Error("Port list is not correct") 261 } 262 263 dockerCmd(c, "run", "--net=host", "busybox", 264 "nc", "localhost", "9876") 265 266 dockerCmd(c, "rm", "-f", firstID) 267 268 if _, _, err := dockerCmdWithError("run", "--net=host", "busybox", 269 "nc", "localhost", "9876"); err == nil { 270 c.Error("Port is still bound after the Container is removed") 271 } 272 } 273 274 func (s *DockerSuite) TestPortExposeHostBinding(c *check.C) { 275 testRequires(c, DaemonIsLinux, NotUserNamespace) 276 out, _ := dockerCmd(c, "run", "-d", "-P", "--expose", "80", "busybox", 277 "nc", "-l", "-p", "80") 278 firstID := strings.TrimSpace(out) 279 280 out, _ = dockerCmd(c, "port", firstID, "80") 281 282 _, exposedPort, err := net.SplitHostPort(out) 283 284 if err != nil { 285 c.Fatal(out, err) 286 } 287 288 dockerCmd(c, "run", "--net=host", "busybox", 289 "nc", "localhost", strings.TrimSpace(exposedPort)) 290 291 dockerCmd(c, "rm", "-f", firstID) 292 293 if _, _, err = dockerCmdWithError("run", "--net=host", "busybox", 294 "nc", "localhost", strings.TrimSpace(exposedPort)); err == nil { 295 c.Error("Port is still bound after the Container is removed") 296 } 297 }