Ver Fonte

Add fallback to resolveSystemAddr() in linux

- So that swarm init will still work w/o specifying the advertise
  address when the daemon is running inside a container

Signed-off-by: Alessandro Boch <aboch@docker.com>
Alessandro Boch há 9 anos atrás
pai
commit
c0b24c600e

+ 95 - 0
daemon/cluster/listen_addr.go

@@ -149,6 +149,101 @@ func resolveInterfaceAddr(specifiedInterface string) (net.IP, error) {
 	return interfaceAddr6, nil
 }
 
+func (c *Cluster) resolveSystemAddrViaSubnetCheck() (net.IP, error) {
+	// Use the system's only IP address, or fail if there are
+	// multiple addresses to choose from. Skip interfaces which
+	// are managed by docker via subnet check.
+	interfaces, err := net.Interfaces()
+	if err != nil {
+		return nil, err
+	}
+
+	var systemAddr net.IP
+	var systemInterface string
+
+	// List Docker-managed subnets
+	v4Subnets := c.config.NetworkSubnetsProvider.V4Subnets()
+	v6Subnets := c.config.NetworkSubnetsProvider.V6Subnets()
+
+ifaceLoop:
+	for _, intf := range interfaces {
+		// Skip inactive interfaces and loopback interfaces
+		if (intf.Flags&net.FlagUp == 0) || (intf.Flags&net.FlagLoopback) != 0 {
+			continue
+		}
+
+		addrs, err := intf.Addrs()
+		if err != nil {
+			continue
+		}
+
+		var interfaceAddr4, interfaceAddr6 net.IP
+
+		for _, addr := range addrs {
+			ipAddr, ok := addr.(*net.IPNet)
+
+			// Skip loopback and link-local addresses
+			if !ok || !ipAddr.IP.IsGlobalUnicast() {
+				continue
+			}
+
+			if ipAddr.IP.To4() != nil {
+				// IPv4
+
+				// Ignore addresses in subnets that are managed by Docker.
+				for _, subnet := range v4Subnets {
+					if subnet.Contains(ipAddr.IP) {
+						continue ifaceLoop
+					}
+				}
+
+				if interfaceAddr4 != nil {
+					return nil, errMultipleIPs(intf.Name, intf.Name, interfaceAddr4, ipAddr.IP)
+				}
+
+				interfaceAddr4 = ipAddr.IP
+			} else {
+				// IPv6
+
+				// Ignore addresses in subnets that are managed by Docker.
+				for _, subnet := range v6Subnets {
+					if subnet.Contains(ipAddr.IP) {
+						continue ifaceLoop
+					}
+				}
+
+				if interfaceAddr6 != nil {
+					return nil, errMultipleIPs(intf.Name, intf.Name, interfaceAddr6, ipAddr.IP)
+				}
+
+				interfaceAddr6 = ipAddr.IP
+			}
+		}
+
+		// In the case that this interface has exactly one IPv4 address
+		// and exactly one IPv6 address, favor IPv4 over IPv6.
+		if interfaceAddr4 != nil {
+			if systemAddr != nil {
+				return nil, errMultipleIPs(systemInterface, intf.Name, systemAddr, interfaceAddr4)
+			}
+			systemAddr = interfaceAddr4
+			systemInterface = intf.Name
+		} else if interfaceAddr6 != nil {
+			if systemAddr != nil {
+				return nil, errMultipleIPs(systemInterface, intf.Name, systemAddr, interfaceAddr6)
+			}
+			systemAddr = interfaceAddr6
+			systemInterface = intf.Name
+		}
+	}
+
+	if systemAddr == nil {
+		return nil, errNoIP
+	}
+
+	return systemAddr, nil
+}
+
 func listSystemIPs() []net.IP {
 	interfaces, err := net.Interfaces()
 	if err != nil {

+ 15 - 2
daemon/cluster/listen_addr_linux.go

@@ -16,8 +16,11 @@ func (c *Cluster) resolveSystemAddr() (net.IP, error) {
 		return nil, err
 	}
 
-	var systemAddr net.IP
-	var systemInterface string
+	var (
+		systemAddr      net.IP
+		systemInterface string
+		deviceFound     bool
+	)
 
 	for _, intf := range interfaces {
 		// Skip non device or inactive interfaces
@@ -40,6 +43,9 @@ func (c *Cluster) resolveSystemAddr() (net.IP, error) {
 				continue
 			}
 
+			// At least one non-loopback device is found and it is administratively up
+			deviceFound = true
+
 			if ipAddr.To4() != nil {
 				if interfaceAddr4 != nil {
 					return nil, errMultipleIPs(intf.Attrs().Name, intf.Attrs().Name, interfaceAddr4, ipAddr)
@@ -71,6 +77,13 @@ func (c *Cluster) resolveSystemAddr() (net.IP, error) {
 	}
 
 	if systemAddr == nil {
+		if !deviceFound {
+			// If no non-loopback device type interface is found,
+			// fall back to the regular auto-detection mechanism.
+			// This is to cover the case where docker is running
+			// inside a container (eths are in fact veths).
+			return c.resolveSystemAddrViaSubnetCheck()
+		}
 		return nil, errNoIP
 	}
 

+ 1 - 91
daemon/cluster/listen_addr_others.go

@@ -5,95 +5,5 @@ package cluster
 import "net"
 
 func (c *Cluster) resolveSystemAddr() (net.IP, error) {
-	// Use the system's only IP address, or fail if there are
-	// multiple addresses to choose from.
-	interfaces, err := net.Interfaces()
-	if err != nil {
-		return nil, err
-	}
-
-	var systemAddr net.IP
-	var systemInterface string
-
-	// List Docker-managed subnets
-	v4Subnets := c.config.NetworkSubnetsProvider.V4Subnets()
-	v6Subnets := c.config.NetworkSubnetsProvider.V6Subnets()
-
-ifaceLoop:
-	for _, intf := range interfaces {
-		// Skip inactive interfaces and loopback interfaces
-		if (intf.Flags&net.FlagUp == 0) || (intf.Flags&net.FlagLoopback) != 0 {
-			continue
-		}
-
-		addrs, err := intf.Addrs()
-		if err != nil {
-			continue
-		}
-
-		var interfaceAddr4, interfaceAddr6 net.IP
-
-		for _, addr := range addrs {
-			ipAddr, ok := addr.(*net.IPNet)
-
-			// Skip loopback and link-local addresses
-			if !ok || !ipAddr.IP.IsGlobalUnicast() {
-				continue
-			}
-
-			if ipAddr.IP.To4() != nil {
-				// IPv4
-
-				// Ignore addresses in subnets that are managed by Docker.
-				for _, subnet := range v4Subnets {
-					if subnet.Contains(ipAddr.IP) {
-						continue ifaceLoop
-					}
-				}
-
-				if interfaceAddr4 != nil {
-					return nil, errMultipleIPs(intf.Name, intf.Name, interfaceAddr4, ipAddr.IP)
-				}
-
-				interfaceAddr4 = ipAddr.IP
-			} else {
-				// IPv6
-
-				// Ignore addresses in subnets that are managed by Docker.
-				for _, subnet := range v6Subnets {
-					if subnet.Contains(ipAddr.IP) {
-						continue ifaceLoop
-					}
-				}
-
-				if interfaceAddr6 != nil {
-					return nil, errMultipleIPs(intf.Name, intf.Name, interfaceAddr6, ipAddr.IP)
-				}
-
-				interfaceAddr6 = ipAddr.IP
-			}
-		}
-
-		// In the case that this interface has exactly one IPv4 address
-		// and exactly one IPv6 address, favor IPv4 over IPv6.
-		if interfaceAddr4 != nil {
-			if systemAddr != nil {
-				return nil, errMultipleIPs(systemInterface, intf.Name, systemAddr, interfaceAddr4)
-			}
-			systemAddr = interfaceAddr4
-			systemInterface = intf.Name
-		} else if interfaceAddr6 != nil {
-			if systemAddr != nil {
-				return nil, errMultipleIPs(systemInterface, intf.Name, systemAddr, interfaceAddr6)
-			}
-			systemAddr = interfaceAddr6
-			systemInterface = intf.Name
-		}
-	}
-
-	if systemAddr == nil {
-		return nil, errNoIP
-	}
-
-	return systemAddr, nil
+	return c.resolveSystemAddrViaSubnetCheck()
 }