Browse code

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 authored on 2015/06/20 13:15:51
Showing 1 changed files
... ...
@@ -768,6 +768,20 @@ func createNetwork(controller libnetwork.NetworkController, dnet string, driver
768 768
 	return controller.NewNetwork(driver, dnet, createOptions...)
769 769
 }
770 770
 
771
+func (container *Container) secondaryNetworkRequired(primaryNetworkType string) bool {
772
+	switch primaryNetworkType {
773
+	case "bridge", "none", "host", "container":
774
+		return false
775
+	}
776
+	if container.Config.ExposedPorts != nil && len(container.Config.ExposedPorts) > 0 {
777
+		return true
778
+	}
779
+	if container.hostConfig.PortBindings != nil && len(container.hostConfig.PortBindings) > 0 {
780
+		return true
781
+	}
782
+	return false
783
+}
784
+
771 785
 func (container *Container) AllocateNetwork() error {
772 786
 	mode := container.hostConfig.NetworkMode
773 787
 	controller := container.daemon.netController
... ...
@@ -775,7 +789,7 @@ func (container *Container) AllocateNetwork() error {
775 775
 		return nil
776 776
 	}
777 777
 
778
-	var networkDriver string
778
+	networkDriver := string(mode)
779 779
 	service := container.Config.PublishService
780 780
 	networkName := mode.NetworkName()
781 781
 	if mode.IsDefault() {
... ...
@@ -797,12 +811,25 @@ func (container *Container) AllocateNetwork() error {
797 797
 		service = strings.Replace(service, "/", "", -1)
798 798
 	}
799 799
 
800
-	var err error
800
+	if container.secondaryNetworkRequired(networkDriver) {
801
+		// Configure Bridge as secondary network for port binding purposes
802
+		if err := container.configureNetwork("bridge", service, "bridge", false); err != nil {
803
+			return err
804
+		}
805
+	}
801 806
 
807
+	if err := container.configureNetwork(networkName, service, networkDriver, mode.IsDefault()); err != nil {
808
+		return err
809
+	}
810
+
811
+	return container.WriteHostConfig()
812
+}
813
+
814
+func (container *Container) configureNetwork(networkName, service, networkDriver string, canCreateNetwork bool) error {
815
+	controller := container.daemon.netController
802 816
 	n, err := controller.NetworkByName(networkName)
803 817
 	if err != nil {
804
-		// Create Network automatically only in default mode
805
-		if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok || !mode.IsDefault() {
818
+		if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok || !canCreateNetwork {
806 819
 			return err
807 820
 		}
808 821
 
... ...
@@ -845,10 +872,6 @@ func (container *Container) AllocateNetwork() error {
845 845
 		return fmt.Errorf("Updating join info failed: %v", err)
846 846
 	}
847 847
 
848
-	if err := container.WriteHostConfig(); err != nil {
849
-		return err
850
-	}
851
-
852 848
 	return nil
853 849
 }
854 850