From 739996c1d78976f7435c7274300b3e8f2e598b17 Mon Sep 17 00:00:00 2001 From: Madhu Venugopal Date: Fri, 19 Jun 2015 21:15:51 -0700 Subject: [PATCH] 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 --- daemon/container_linux.go | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/daemon/container_linux.go b/daemon/container_linux.go index 335d3f19b1..0a5bf38725 100644 --- a/daemon/container_linux.go +++ b/daemon/container_linux.go @@ -768,6 +768,20 @@ func createNetwork(controller libnetwork.NetworkController, dnet string, driver 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 { mode := container.hostConfig.NetworkMode controller := container.daemon.netController @@ -775,7 +789,7 @@ func (container *Container) AllocateNetwork() error { return nil } - var networkDriver string + networkDriver := string(mode) service := container.Config.PublishService networkName := mode.NetworkName() if mode.IsDefault() { @@ -797,12 +811,25 @@ func (container *Container) AllocateNetwork() error { 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) 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 } @@ -845,10 +872,6 @@ func (container *Container) AllocateNetwork() error { return fmt.Errorf("Updating join info failed: %v", err) } - if err := container.WriteHostConfig(); err != nil { - return err - } - return nil }