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>
| ... | ... |
@@ -11,7 +11,6 @@ import ( |
| 11 | 11 |
log "github.com/Sirupsen/logrus" |
| 12 | 12 |
"github.com/docker/docker/daemon/networkdriver" |
| 13 | 13 |
"github.com/docker/docker/daemon/networkdriver/ipallocator" |
| 14 |
- "github.com/docker/docker/daemon/networkdriver/portallocator" |
|
| 15 | 14 |
"github.com/docker/docker/daemon/networkdriver/portmapper" |
| 16 | 15 |
"github.com/docker/docker/engine" |
| 17 | 16 |
"github.com/docker/docker/nat" |
| ... | ... |
@@ -468,22 +467,13 @@ func AllocatePort(job *engine.Job) engine.Status {
|
| 468 | 468 |
if host, err = portmapper.Map(container, ip, hostPort); err == nil {
|
| 469 | 469 |
break |
| 470 | 470 |
} |
| 471 |
- |
|
| 472 |
- if allocerr, ok := err.(portallocator.ErrPortAlreadyAllocated); ok {
|
|
| 473 |
- // There is no point in immediately retrying to map an explicitly |
|
| 474 |
- // chosen port. |
|
| 475 |
- if hostPort != 0 {
|
|
| 476 |
- job.Logf("Failed to bind %s for container address %s: %s", allocerr.IPPort(), container.String(), allocerr.Error())
|
|
| 477 |
- break |
|
| 478 |
- } |
|
| 479 |
- |
|
| 480 |
- // Automatically chosen 'free' port failed to bind: move on the next. |
|
| 481 |
- job.Logf("Failed to bind %s for container address %s. Trying another port.", allocerr.IPPort(), container.String())
|
|
| 482 |
- } else {
|
|
| 483 |
- // some other error during mapping |
|
| 484 |
- job.Logf("Received an unexpected error during port allocation: %s", err.Error())
|
|
| 471 |
+ // There is no point in immediately retrying to map an explicitly |
|
| 472 |
+ // chosen port. |
|
| 473 |
+ if hostPort != 0 {
|
|
| 474 |
+ job.Logf("Failed to allocate and map port %d: %s", hostPort, err)
|
|
| 485 | 475 |
break |
| 486 | 476 |
} |
| 477 |
+ job.Logf("Failed to allocate and map port: %s, retry: %d", err, i+1)
|
|
| 487 | 478 |
} |
| 488 | 479 |
|
| 489 | 480 |
if err != nil {
|
| ... | ... |
@@ -2701,3 +2701,44 @@ func TestRunTLSverify(t *testing.T) {
|
| 2701 | 2701 |
|
| 2702 | 2702 |
logDone("run - verify tls is set for --tlsverify")
|
| 2703 | 2703 |
} |
| 2704 |
+ |
|
| 2705 |
+func TestRunPortFromDockerRangeInUse(t *testing.T) {
|
|
| 2706 |
+ defer deleteAllContainers() |
|
| 2707 |
+ // first find allocator current position |
|
| 2708 |
+ cmd := exec.Command(dockerBinary, "run", "-d", "-p", ":80", "busybox", "top") |
|
| 2709 |
+ out, _, err := runCommandWithOutput(cmd) |
|
| 2710 |
+ if err != nil {
|
|
| 2711 |
+ t.Fatal(out, err) |
|
| 2712 |
+ } |
|
| 2713 |
+ id := strings.TrimSpace(out) |
|
| 2714 |
+ cmd = exec.Command(dockerBinary, "port", id) |
|
| 2715 |
+ out, _, err = runCommandWithOutput(cmd) |
|
| 2716 |
+ if err != nil {
|
|
| 2717 |
+ t.Fatal(out, err) |
|
| 2718 |
+ } |
|
| 2719 |
+ out = strings.TrimSpace(out) |
|
| 2720 |
+ out = strings.Split(out, ":")[1] |
|
| 2721 |
+ lastPort, err := strconv.Atoi(out) |
|
| 2722 |
+ if err != nil {
|
|
| 2723 |
+ t.Fatal(err) |
|
| 2724 |
+ } |
|
| 2725 |
+ port := lastPort + 1 |
|
| 2726 |
+ l, err := net.Listen("tcp", ":"+strconv.Itoa(port))
|
|
| 2727 |
+ if err != nil {
|
|
| 2728 |
+ t.Fatal(err) |
|
| 2729 |
+ } |
|
| 2730 |
+ defer l.Close() |
|
| 2731 |
+ cmd = exec.Command(dockerBinary, "run", "-d", "-p", ":80", "busybox", "top") |
|
| 2732 |
+ out, _, err = runCommandWithOutput(cmd) |
|
| 2733 |
+ if err != nil {
|
|
| 2734 |
+ t.Fatalf(out, err) |
|
| 2735 |
+ } |
|
| 2736 |
+ id = strings.TrimSpace(out) |
|
| 2737 |
+ cmd = exec.Command(dockerBinary, "port", id) |
|
| 2738 |
+ out, _, err = runCommandWithOutput(cmd) |
|
| 2739 |
+ if err != nil {
|
|
| 2740 |
+ t.Fatal(out, err) |
|
| 2741 |
+ } |
|
| 2742 |
+ |
|
| 2743 |
+ logDone("run - find another port if port from autorange already bound")
|
|
| 2744 |
+} |