Sfoglia il codice sorgente

Try other port on any error from Map

Sometimes other programs can bind on ports from our range, so we just
skip this ports on allocation.

Fixes #9293
Probably fixes #8714

Signed-off-by: Alexander Morozov <lk4d4@docker.com>
Alexandr Morozov 10 anni fa
parent
commit
a00a1a1fca

+ 5 - 15
daemon/networkdriver/bridge/driver.go

@@ -11,7 +11,6 @@ import (
 	log "github.com/Sirupsen/logrus"
 	"github.com/docker/docker/daemon/networkdriver"
 	"github.com/docker/docker/daemon/networkdriver/ipallocator"
-	"github.com/docker/docker/daemon/networkdriver/portallocator"
 	"github.com/docker/docker/daemon/networkdriver/portmapper"
 	"github.com/docker/docker/engine"
 	"github.com/docker/docker/nat"
@@ -468,22 +467,13 @@ func AllocatePort(job *engine.Job) engine.Status {
 		if host, err = portmapper.Map(container, ip, hostPort); err == nil {
 			break
 		}
-
-		if allocerr, ok := err.(portallocator.ErrPortAlreadyAllocated); ok {
-			// There is no point in immediately retrying to map an explicitly
-			// chosen port.
-			if hostPort != 0 {
-				job.Logf("Failed to bind %s for container address %s: %s", allocerr.IPPort(), container.String(), allocerr.Error())
-				break
-			}
-
-			// Automatically chosen 'free' port failed to bind: move on the next.
-			job.Logf("Failed to bind %s for container address %s. Trying another port.", allocerr.IPPort(), container.String())
-		} else {
-			// some other error during mapping
-			job.Logf("Received an unexpected error during port allocation: %s", err.Error())
+		// There is no point in immediately retrying to map an explicitly
+		// chosen port.
+		if hostPort != 0 {
+			job.Logf("Failed to allocate and map port %d: %s", hostPort, err)
 			break
 		}
+		job.Logf("Failed to allocate and map port: %s, retry: %d", err, i+1)
 	}
 
 	if err != nil {

+ 41 - 0
integration-cli/docker_cli_run_test.go

@@ -2701,3 +2701,44 @@ func TestRunTLSverify(t *testing.T) {
 
 	logDone("run - verify tls is set for --tlsverify")
 }
+
+func TestRunPortFromDockerRangeInUse(t *testing.T) {
+	defer deleteAllContainers()
+	// first find allocator current position
+	cmd := exec.Command(dockerBinary, "run", "-d", "-p", ":80", "busybox", "top")
+	out, _, err := runCommandWithOutput(cmd)
+	if err != nil {
+		t.Fatal(out, err)
+	}
+	id := strings.TrimSpace(out)
+	cmd = exec.Command(dockerBinary, "port", id)
+	out, _, err = runCommandWithOutput(cmd)
+	if err != nil {
+		t.Fatal(out, err)
+	}
+	out = strings.TrimSpace(out)
+	out = strings.Split(out, ":")[1]
+	lastPort, err := strconv.Atoi(out)
+	if err != nil {
+		t.Fatal(err)
+	}
+	port := lastPort + 1
+	l, err := net.Listen("tcp", ":"+strconv.Itoa(port))
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer l.Close()
+	cmd = exec.Command(dockerBinary, "run", "-d", "-p", ":80", "busybox", "top")
+	out, _, err = runCommandWithOutput(cmd)
+	if err != nil {
+		t.Fatalf(out, err)
+	}
+	id = strings.TrimSpace(out)
+	cmd = exec.Command(dockerBinary, "port", id)
+	out, _, err = runCommandWithOutput(cmd)
+	if err != nil {
+		t.Fatal(out, err)
+	}
+
+	logDone("run - find another port if port from autorange already bound")
+}