diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index ba0c423aaf..cec079b0f2 100644 --- a/daemon/daemon_unix.go +++ b/daemon/daemon_unix.go @@ -39,6 +39,7 @@ import ( "github.com/opencontainers/runc/libcontainer/label" "github.com/opencontainers/runc/libcontainer/user" "github.com/opencontainers/runtime-spec/specs-go" + "github.com/vishvananda/netlink" ) const ( @@ -637,11 +638,21 @@ func (daemon *Daemon) initNetworkController(config *Config, activeSandboxes map[ return nil, fmt.Errorf("Error creating default \"host\" network: %v", err) } } + + // Clear stale bridge network + if n, err := controller.NetworkByName("bridge"); err == nil { + if err = n.Delete(); err != nil { + return nil, fmt.Errorf("could not delete the default bridge network: %v", err) + } + } + if !config.DisableBridge { // Initialize default driver "bridge" if err := initBridgeDriver(controller, config); err != nil { return nil, err } + } else { + removeDefaultBridgeInterface() } return controller, nil @@ -660,12 +671,6 @@ func driverOptions(config *Config) []nwconfig.Option { } func initBridgeDriver(controller libnetwork.NetworkController, config *Config) error { - if n, err := controller.NetworkByName("bridge"); err == nil { - if err = n.Delete(); err != nil { - return fmt.Errorf("could not delete the default bridge network: %v", err) - } - } - bridgeName := bridge.DefaultBridgeName if config.bridgeConfig.Iface != "" { bridgeName = config.bridgeConfig.Iface @@ -779,6 +784,15 @@ func initBridgeDriver(controller libnetwork.NetworkController, config *Config) e return nil } +// Remove default bridge interface if present (--bridge=none use case) +func removeDefaultBridgeInterface() { + if lnk, err := netlink.LinkByName(bridge.DefaultBridgeName); err == nil { + if err := netlink.LinkDel(lnk); err != nil { + logrus.Warnf("Failed to remove bridge interface (%s): %v", bridge.DefaultBridgeName, err) + } + } +} + func (daemon *Daemon) getLayerInit() func(string) error { return daemon.setupInitLayer } diff --git a/integration-cli/docker_cli_daemon_test.go b/integration-cli/docker_cli_daemon_test.go index b9d3c6c807..68aa1f3267 100644 --- a/integration-cli/docker_cli_daemon_test.go +++ b/integration-cli/docker_cli_daemon_test.go @@ -643,6 +643,24 @@ func (s *DockerDaemonSuite) TestDaemonBridgeExternal(c *check.C) { containerIP)) } +func (s *DockerDaemonSuite) TestDaemonBridgeNone(c *check.C) { + // start with bridge none + d := s.d + err := d.StartWithBusybox("--bridge", "none") + c.Assert(err, check.IsNil) + defer d.Restart() + + // verify docker0 iface is not there + out, _, err := runCommandWithOutput(exec.Command("ifconfig", "docker0")) + c.Assert(err, check.NotNil, check.Commentf("docker0 should not be present if daemon started with --bridge=none")) + c.Assert(strings.Contains(out, "Device not found"), check.Equals, true) + + // verify default "bridge" network is not there + out, err = d.Cmd("network", "inspect", "bridge") + c.Assert(err, check.NotNil, check.Commentf("\"bridge\" network should not be present if daemon started with --bridge=none")) + c.Assert(strings.Contains(out, "No such network"), check.Equals, true) +} + func createInterface(c *check.C, ifType string, ifName string, ipNet string) (string, error) { args := []string{"link", "add", "name", ifName, "type", ifType} ipLinkCmd := exec.Command("ip", args...)