Browse Source

Adding container to secondary network to support port mapping

With publish-service and default-network support, a container could be
connected to a user-defined network that is backed by any driver/plugin.
But if the user uses port mapping or expose commands, the expectation
for that container is to behave like existing bridge network.
Thanks to the Libnetwork's CNM model, containers can be connected
to the bridge network as a secondary network in addition to the
user-specified network.

Signed-off-by: Madhu Venugopal <madhu@docker.com>
Madhu Venugopal 10 năm trước cách đây
mục cha
commit
739996c1d7
1 tập tin đã thay đổi với 31 bổ sung8 xóa
  1. 31 8
      daemon/container_linux.go

+ 31 - 8
daemon/container_linux.go

@@ -768,6 +768,20 @@ func createNetwork(controller libnetwork.NetworkController, dnet string, driver
 	return controller.NewNetwork(driver, dnet, createOptions...)
 	return controller.NewNetwork(driver, dnet, createOptions...)
 }
 }
 
 
+func (container *Container) secondaryNetworkRequired(primaryNetworkType string) bool {
+	switch primaryNetworkType {
+	case "bridge", "none", "host", "container":
+		return false
+	}
+	if container.Config.ExposedPorts != nil && len(container.Config.ExposedPorts) > 0 {
+		return true
+	}
+	if container.hostConfig.PortBindings != nil && len(container.hostConfig.PortBindings) > 0 {
+		return true
+	}
+	return false
+}
+
 func (container *Container) AllocateNetwork() error {
 func (container *Container) AllocateNetwork() error {
 	mode := container.hostConfig.NetworkMode
 	mode := container.hostConfig.NetworkMode
 	controller := container.daemon.netController
 	controller := container.daemon.netController
@@ -775,7 +789,7 @@ func (container *Container) AllocateNetwork() error {
 		return nil
 		return nil
 	}
 	}
 
 
-	var networkDriver string
+	networkDriver := string(mode)
 	service := container.Config.PublishService
 	service := container.Config.PublishService
 	networkName := mode.NetworkName()
 	networkName := mode.NetworkName()
 	if mode.IsDefault() {
 	if mode.IsDefault() {
@@ -797,12 +811,25 @@ func (container *Container) AllocateNetwork() error {
 		service = strings.Replace(service, "/", "", -1)
 		service = strings.Replace(service, "/", "", -1)
 	}
 	}
 
 
-	var err error
+	if container.secondaryNetworkRequired(networkDriver) {
+		// Configure Bridge as secondary network for port binding purposes
+		if err := container.configureNetwork("bridge", service, "bridge", false); err != nil {
+			return err
+		}
+	}
 
 
+	if err := container.configureNetwork(networkName, service, networkDriver, mode.IsDefault()); err != nil {
+		return err
+	}
+
+	return container.WriteHostConfig()
+}
+
+func (container *Container) configureNetwork(networkName, service, networkDriver string, canCreateNetwork bool) error {
+	controller := container.daemon.netController
 	n, err := controller.NetworkByName(networkName)
 	n, err := controller.NetworkByName(networkName)
 	if err != nil {
 	if err != nil {
-		// Create Network automatically only in default mode
-		if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok || !mode.IsDefault() {
+		if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok || !canCreateNetwork {
 			return err
 			return err
 		}
 		}
 
 
@@ -845,10 +872,6 @@ func (container *Container) AllocateNetwork() error {
 		return fmt.Errorf("Updating join info failed: %v", err)
 		return fmt.Errorf("Updating join info failed: %v", err)
 	}
 	}
 
 
-	if err := container.WriteHostConfig(); err != nil {
-		return err
-	}
-
 	return nil
 	return nil
 }
 }