github.com/endophage/docker@v1.4.2-0.20161027011718-242853499895/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/docker/docker/pkg/integration/checker"
    11  	"github.com/go-check/check"
    12  )
    13  
    14  func (s *DockerSuite) TestPortList(c *check.C) {
    15  	testRequires(c, DaemonIsLinux)
    16  	// one port
    17  	out, _ := dockerCmd(c, "run", "-d", "-p", "9876:80", "busybox", "top")
    18  	firstID := strings.TrimSpace(out)
    19  
    20  	out, _ = dockerCmd(c, "port", firstID, "80")
    21  
    22  	err := assertPortList(c, out, []string{"0.0.0.0:9876"})
    23  	// Port list is not correct
    24  	c.Assert(err, checker.IsNil)
    25  
    26  	out, _ = dockerCmd(c, "port", firstID)
    27  
    28  	err = assertPortList(c, out, []string{"80/tcp -> 0.0.0.0:9876"})
    29  	// Port list is not correct
    30  	c.Assert(err, checker.IsNil)
    31  
    32  	dockerCmd(c, "rm", "-f", firstID)
    33  
    34  	// three port
    35  	out, _ = dockerCmd(c, "run", "-d",
    36  		"-p", "9876:80",
    37  		"-p", "9877:81",
    38  		"-p", "9878:82",
    39  		"busybox", "top")
    40  	ID := strings.TrimSpace(out)
    41  
    42  	out, _ = dockerCmd(c, "port", ID, "80")
    43  
    44  	err = assertPortList(c, out, []string{"0.0.0.0:9876"})
    45  	// Port list is not correct
    46  	c.Assert(err, checker.IsNil)
    47  
    48  	out, _ = dockerCmd(c, "port", ID)
    49  
    50  	err = assertPortList(c, out, []string{
    51  		"80/tcp -> 0.0.0.0:9876",
    52  		"81/tcp -> 0.0.0.0:9877",
    53  		"82/tcp -> 0.0.0.0:9878"})
    54  	// Port list is not correct
    55  	c.Assert(err, checker.IsNil)
    56  
    57  	dockerCmd(c, "rm", "-f", ID)
    58  
    59  	// more and one port mapped to the same container port
    60  	out, _ = dockerCmd(c, "run", "-d",
    61  		"-p", "9876:80",
    62  		"-p", "9999:80",
    63  		"-p", "9877:81",
    64  		"-p", "9878:82",
    65  		"busybox", "top")
    66  	ID = strings.TrimSpace(out)
    67  
    68  	out, _ = dockerCmd(c, "port", ID, "80")
    69  
    70  	err = assertPortList(c, out, []string{"0.0.0.0:9876", "0.0.0.0:9999"})
    71  	// Port list is not correct
    72  	c.Assert(err, checker.IsNil)
    73  
    74  	out, _ = dockerCmd(c, "port", ID)
    75  
    76  	err = assertPortList(c, out, []string{
    77  		"80/tcp -> 0.0.0.0:9876",
    78  		"80/tcp -> 0.0.0.0:9999",
    79  		"81/tcp -> 0.0.0.0:9877",
    80  		"82/tcp -> 0.0.0.0:9878"})
    81  	// Port list is not correct
    82  	c.Assert(err, checker.IsNil)
    83  	dockerCmd(c, "rm", "-f", ID)
    84  
    85  	testRange := func() {
    86  		// host port ranges used
    87  		IDs := make([]string, 3)
    88  		for i := 0; i < 3; i++ {
    89  			out, _ = dockerCmd(c, "run", "-d",
    90  				"-p", "9090-9092:80",
    91  				"busybox", "top")
    92  			IDs[i] = strings.TrimSpace(out)
    93  
    94  			out, _ = dockerCmd(c, "port", IDs[i])
    95  
    96  			err = assertPortList(c, out, []string{fmt.Sprintf("80/tcp -> 0.0.0.0:%d", 9090+i)})
    97  			// Port list is not correct
    98  			c.Assert(err, checker.IsNil)
    99  		}
   100  
   101  		// test port range exhaustion
   102  		out, _, err = dockerCmdWithError("run", "-d",
   103  			"-p", "9090-9092:80",
   104  			"busybox", "top")
   105  		// Exhausted port range did not return an error
   106  		c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
   107  
   108  		for i := 0; i < 3; i++ {
   109  			dockerCmd(c, "rm", "-f", IDs[i])
   110  		}
   111  	}
   112  	testRange()
   113  	// Verify we ran re-use port ranges after they are no longer in use.
   114  	testRange()
   115  
   116  	// test invalid port ranges
   117  	for _, invalidRange := range []string{"9090-9089:80", "9090-:80", "-9090:80"} {
   118  		out, _, err = dockerCmdWithError("run", "-d",
   119  			"-p", invalidRange,
   120  			"busybox", "top")
   121  		// Port range should have returned an error
   122  		c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
   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  	err = 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  	// Port list is not correct
   139  	c.Assert(err, checker.IsNil)
   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  	err = assertPortList(c, out, []string{
   152  		"80/tcp -> 0.0.0.0:8000",
   153  		"80/udp -> 0.0.0.0:8000"})
   154  	// Port list is not correct
   155  	c.Assert(err, checker.IsNil)
   156  	dockerCmd(c, "rm", "-f", ID)
   157  }
   158  
   159  func assertPortList(c *check.C, out string, expected []string) error {
   160  	lines := strings.Split(strings.Trim(out, "\n "), "\n")
   161  	if len(lines) != len(expected) {
   162  		return fmt.Errorf("different size lists %s, %d, %d", out, len(lines), len(expected))
   163  	}
   164  	sort.Strings(lines)
   165  	sort.Strings(expected)
   166  
   167  	for i := 0; i < len(expected); i++ {
   168  		if lines[i] != expected[i] {
   169  			return fmt.Errorf("|" + lines[i] + "!=" + expected[i] + "|")
   170  		}
   171  	}
   172  
   173  	return nil
   174  }
   175  
   176  func stopRemoveContainer(id string, c *check.C) {
   177  	dockerCmd(c, "rm", "-f", id)
   178  }
   179  
   180  func (s *DockerSuite) TestUnpublishedPortsInPsOutput(c *check.C) {
   181  	testRequires(c, DaemonIsLinux)
   182  	// Run busybox with command line expose (equivalent to EXPOSE in image's Dockerfile) for the following ports
   183  	port1 := 80
   184  	port2 := 443
   185  	expose1 := fmt.Sprintf("--expose=%d", port1)
   186  	expose2 := fmt.Sprintf("--expose=%d", port2)
   187  	dockerCmd(c, "run", "-d", expose1, expose2, "busybox", "sleep", "5")
   188  
   189  	// Check docker ps o/p for last created container reports the unpublished ports
   190  	unpPort1 := fmt.Sprintf("%d/tcp", port1)
   191  	unpPort2 := fmt.Sprintf("%d/tcp", port2)
   192  	out, _ := dockerCmd(c, "ps", "-n=1")
   193  	// Missing unpublished ports in docker ps output
   194  	c.Assert(out, checker.Contains, unpPort1)
   195  	// Missing unpublished ports in docker ps output
   196  	c.Assert(out, checker.Contains, unpPort2)
   197  
   198  	// Run the container forcing to publish the exposed ports
   199  	dockerCmd(c, "run", "-d", "-P", expose1, expose2, "busybox", "sleep", "5")
   200  
   201  	// Check docker ps o/p for last created container reports the exposed ports in the port bindings
   202  	expBndRegx1 := regexp.MustCompile(`0.0.0.0:\d\d\d\d\d->` + unpPort1)
   203  	expBndRegx2 := regexp.MustCompile(`0.0.0.0:\d\d\d\d\d->` + unpPort2)
   204  	out, _ = dockerCmd(c, "ps", "-n=1")
   205  	// Cannot find expected port binding port (0.0.0.0:xxxxx->unpPort1) in docker ps output
   206  	c.Assert(expBndRegx1.MatchString(out), checker.Equals, true, check.Commentf("out: %s; unpPort1: %s", out, unpPort1))
   207  	// Cannot find expected port binding port (0.0.0.0:xxxxx->unpPort2) in docker ps output
   208  	c.Assert(expBndRegx2.MatchString(out), checker.Equals, true, check.Commentf("out: %s; unpPort2: %s", out, unpPort2))
   209  
   210  	// Run the container specifying explicit port bindings for the exposed ports
   211  	offset := 10000
   212  	pFlag1 := fmt.Sprintf("%d:%d", offset+port1, port1)
   213  	pFlag2 := fmt.Sprintf("%d:%d", offset+port2, port2)
   214  	out, _ = dockerCmd(c, "run", "-d", "-p", pFlag1, "-p", pFlag2, expose1, expose2, "busybox", "sleep", "5")
   215  	id := strings.TrimSpace(out)
   216  
   217  	// Check docker ps o/p for last created container reports the specified port mappings
   218  	expBnd1 := fmt.Sprintf("0.0.0.0:%d->%s", offset+port1, unpPort1)
   219  	expBnd2 := fmt.Sprintf("0.0.0.0:%d->%s", offset+port2, unpPort2)
   220  	out, _ = dockerCmd(c, "ps", "-n=1")
   221  	// Cannot find expected port binding (expBnd1) in docker ps output
   222  	c.Assert(out, checker.Contains, expBnd1)
   223  	// Cannot find expected port binding (expBnd2) in docker ps output
   224  	c.Assert(out, checker.Contains, expBnd2)
   225  
   226  	// Remove container now otherwise it will interfere 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  	// Cannot find expected port binding (expBnd1) in docker ps output
   236  	c.Assert(out, checker.Contains, expBnd1)
   237  	// Cannot find expected port binding (expBnd2) in docker ps output
   238  	c.Assert(out, checker.Contains, expBnd2)
   239  	// Remove container now otherwise it will interfere with next test
   240  	stopRemoveContainer(id, c)
   241  
   242  	// Run the container with one unpublished exposed port and one explicit port binding
   243  	dockerCmd(c, "run", "-d", expose1, "-p", pFlag2, "busybox", "sleep", "5")
   244  
   245  	// Check docker ps o/p for last created container reports the specified unpublished port and port mapping
   246  	out, _ = dockerCmd(c, "ps", "-n=1")
   247  	// Missing unpublished exposed ports (unpPort1) in docker ps output
   248  	c.Assert(out, checker.Contains, unpPort1)
   249  	// Missing port binding (expBnd2) in docker ps output
   250  	c.Assert(out, checker.Contains, expBnd2)
   251  }
   252  
   253  func (s *DockerSuite) TestPortHostBinding(c *check.C) {
   254  	testRequires(c, DaemonIsLinux, NotUserNamespace)
   255  	out, _ := dockerCmd(c, "run", "-d", "-p", "9876:80", "busybox",
   256  		"nc", "-l", "-p", "80")
   257  	firstID := strings.TrimSpace(out)
   258  
   259  	out, _ = dockerCmd(c, "port", firstID, "80")
   260  
   261  	err := assertPortList(c, out, []string{"0.0.0.0:9876"})
   262  	// Port list is not correct
   263  	c.Assert(err, checker.IsNil)
   264  
   265  	dockerCmd(c, "run", "--net=host", "busybox",
   266  		"nc", "localhost", "9876")
   267  
   268  	dockerCmd(c, "rm", "-f", firstID)
   269  
   270  	out, _, err = dockerCmdWithError("run", "--net=host", "busybox", "nc", "localhost", "9876")
   271  	// Port is still bound after the Container is removed
   272  	c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
   273  }
   274  
   275  func (s *DockerSuite) TestPortExposeHostBinding(c *check.C) {
   276  	testRequires(c, DaemonIsLinux, NotUserNamespace)
   277  	out, _ := dockerCmd(c, "run", "-d", "-P", "--expose", "80", "busybox",
   278  		"nc", "-l", "-p", "80")
   279  	firstID := strings.TrimSpace(out)
   280  
   281  	out, _ = dockerCmd(c, "port", firstID, "80")
   282  
   283  	_, exposedPort, err := net.SplitHostPort(out)
   284  	c.Assert(err, checker.IsNil, check.Commentf("out: %s", out))
   285  
   286  	dockerCmd(c, "run", "--net=host", "busybox",
   287  		"nc", "localhost", strings.TrimSpace(exposedPort))
   288  
   289  	dockerCmd(c, "rm", "-f", firstID)
   290  
   291  	out, _, err = dockerCmdWithError("run", "--net=host", "busybox",
   292  		"nc", "localhost", strings.TrimSpace(exposedPort))
   293  	// Port is still bound after the Container is removed
   294  	c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
   295  }
   296  
   297  func (s *DockerSuite) TestPortBindingOnSandbox(c *check.C) {
   298  	testRequires(c, DaemonIsLinux, NotUserNamespace)
   299  	dockerCmd(c, "network", "create", "--internal", "-d", "bridge", "internal-net")
   300  	nr := getNetworkResource(c, "internal-net")
   301  	c.Assert(nr.Internal, checker.Equals, true)
   302  
   303  	dockerCmd(c, "run", "--net", "internal-net", "-d", "--name", "c1",
   304  		"-p", "8080:8080", "busybox", "nc", "-l", "-p", "8080")
   305  	c.Assert(waitRun("c1"), check.IsNil)
   306  
   307  	_, _, err := dockerCmdWithError("run", "--net=host", "busybox", "nc", "localhost", "8080")
   308  	c.Assert(err, check.NotNil,
   309  		check.Commentf("Port mapping on internal network is expected to fail"))
   310  
   311  	// Connect container to another normal bridge network
   312  	dockerCmd(c, "network", "create", "-d", "bridge", "foo-net")
   313  	dockerCmd(c, "network", "connect", "foo-net", "c1")
   314  
   315  	_, _, err = dockerCmdWithError("run", "--net=host", "busybox", "nc", "localhost", "8080")
   316  	c.Assert(err, check.IsNil,
   317  		check.Commentf("Port mapping on the new network is expected to succeed"))
   318  
   319  }