github.com/clintkitson/docker@v1.9.1/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  }