Pārlūkot izejas kodu

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 gadi atpakaļ
vecāks
revīzija
a00a1a1fca

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

@@ -11,7 +11,6 @@ import (
 	log "github.com/Sirupsen/logrus"
 	log "github.com/Sirupsen/logrus"
 	"github.com/docker/docker/daemon/networkdriver"
 	"github.com/docker/docker/daemon/networkdriver"
 	"github.com/docker/docker/daemon/networkdriver/ipallocator"
 	"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/daemon/networkdriver/portmapper"
 	"github.com/docker/docker/engine"
 	"github.com/docker/docker/engine"
 	"github.com/docker/docker/nat"
 	"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 {
 		if host, err = portmapper.Map(container, ip, hostPort); err == nil {
 			break
 			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
 			break
 		}
 		}
+		job.Logf("Failed to allocate and map port: %s, retry: %d", err, i+1)
 	}
 	}
 
 
 	if err != nil {
 	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")
 	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")
+}