Selaa lähdekoodia

Merge pull request #9181 from icecrime/allocate_daemon_ports

Allocate daemon listening ports
Michael Crosby 10 vuotta sitten
vanhempi
commit
21bba5d93a
2 muutettua tiedostoa jossa 62 lisäystä ja 0 poistoa
  1. 31 0
      api/server/server.go
  2. 31 0
      integration-cli/docker_cli_daemon_test.go

+ 31 - 0
api/server/server.go

@@ -27,6 +27,7 @@ import (
 
 	log "github.com/Sirupsen/logrus"
 	"github.com/docker/docker/api"
+	"github.com/docker/docker/daemon/networkdriver/portallocator"
 	"github.com/docker/docker/engine"
 	"github.com/docker/docker/pkg/listenbuffer"
 	"github.com/docker/docker/pkg/parsers"
@@ -1502,6 +1503,32 @@ func setupUnixHttp(addr string, job *engine.Job) (*HttpServer, error) {
 	return &HttpServer{&http.Server{Addr: addr, Handler: r}, l}, nil
 }
 
+func allocateDaemonPort(addr string) error {
+	host, port, err := net.SplitHostPort(addr)
+	if err != nil {
+		return err
+	}
+
+	intPort, err := strconv.Atoi(port)
+	if err != nil {
+		return err
+	}
+
+	var hostIPs []net.IP
+	if parsedIP := net.ParseIP(host); parsedIP != nil {
+		hostIPs = append(hostIPs, parsedIP)
+	} else if hostIPs, err = net.LookupIP(host); err != nil {
+		return fmt.Errorf("failed to lookup %s address in host specification", host)
+	}
+
+	for _, hostIP := range hostIPs {
+		if _, err := portallocator.RequestPort(hostIP, "tcp", intPort); err != nil {
+			return fmt.Errorf("failed to allocate daemon listening port %d (err: %v)", intPort, err)
+		}
+	}
+	return nil
+}
+
 func setupTcpHttp(addr string, job *engine.Job) (*HttpServer, error) {
 	if !strings.HasPrefix(addr, "127.0.0.1") && !job.GetenvBool("TlsVerify") {
 		log.Infof("/!\\ DON'T BIND ON ANOTHER IP ADDRESS THAN 127.0.0.1 IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
@@ -1517,6 +1544,10 @@ func setupTcpHttp(addr string, job *engine.Job) (*HttpServer, error) {
 		return nil, err
 	}
 
+	if err := allocateDaemonPort(addr); err != nil {
+		return nil, err
+	}
+
 	if job.GetenvBool("Tls") || job.GetenvBool("TlsVerify") {
 		var tlsCa string
 		if job.GetenvBool("TlsVerify") {

+ 31 - 0
integration-cli/docker_cli_daemon_test.go

@@ -2,6 +2,7 @@ package main
 
 import (
 	"encoding/json"
+	"fmt"
 	"io/ioutil"
 	"os"
 	"os/exec"
@@ -284,3 +285,33 @@ func TestDaemonLoggingLevel(t *testing.T) {
 
 	logDone("daemon - Logging Level")
 }
+
+func TestDaemonAllocatesListeningPort(t *testing.T) {
+	listeningPorts := [][]string{
+		{"0.0.0.0", "0.0.0.0", "5678"},
+		{"127.0.0.1", "127.0.0.1", "1234"},
+		{"localhost", "127.0.0.1", "1235"},
+	}
+
+	cmdArgs := []string{}
+	for _, hostDirective := range listeningPorts {
+		cmdArgs = append(cmdArgs, "--host", fmt.Sprintf("tcp://%s:%s", hostDirective[0], hostDirective[2]))
+	}
+
+	d := NewDaemon(t)
+	if err := d.StartWithBusybox(cmdArgs...); err != nil {
+		t.Fatalf("Could not start daemon with busybox: %v", err)
+	}
+	defer d.Stop()
+
+	for _, hostDirective := range listeningPorts {
+		output, err := d.Cmd("run", "-p", fmt.Sprintf("%s:%s:80", hostDirective[1], hostDirective[2]), "busybox", "true")
+		if err == nil {
+			t.Fatalf("Container should not start, expected port already allocated error: %q", output)
+		} else if !strings.Contains(output, "port is already allocated") {
+			t.Fatalf("Expected port is already allocated error: %q", output)
+		}
+	}
+
+	logDone("daemon - daemon listening port is allocated")
+}