diff --git a/api/types/container/host_config.go b/api/types/container/host_config.go index 15a84b82d7..c8f72f8c89 100644 --- a/api/types/container/host_config.go +++ b/api/types/container/host_config.go @@ -10,9 +10,6 @@ import ( "github.com/docker/go-units" ) -// NetworkMode represents the container network stack. -type NetworkMode string - // Isolation represents the isolation technology of a container. The supported // values are platform specific type Isolation string @@ -66,6 +63,47 @@ func (n IpcMode) Container() string { return "" } +// NetworkMode represents the container network stack. +type NetworkMode string + +// IsNone indicates whether container isn't using a network stack. +func (n NetworkMode) IsNone() bool { + return n == "none" +} + +// IsDefault indicates whether container uses the default network stack. +func (n NetworkMode) IsDefault() bool { + return n == "default" +} + +// IsPrivate indicates whether container uses its private network stack. +func (n NetworkMode) IsPrivate() bool { + return !(n.IsHost() || n.IsContainer()) +} + +// IsContainer indicates whether container uses a container network stack. +func (n NetworkMode) IsContainer() bool { + parts := strings.SplitN(string(n), ":", 2) + return len(parts) > 1 && parts[0] == "container" +} + +// ConnectedContainer is the id of the container which network this container is connected to. +func (n NetworkMode) ConnectedContainer() string { + parts := strings.SplitN(string(n), ":", 2) + if len(parts) > 1 { + return parts[1] + } + return "" +} + +//UserDefined indicates user-created network +func (n NetworkMode) UserDefined() string { + if n.IsUserDefined() { + return string(n) + } + return "" +} + // UsernsMode represents userns mode in the container. type UsernsMode string diff --git a/api/types/container/hostconfig_unix.go b/api/types/container/hostconfig_unix.go index 9fb79bed6f..2d664d1c96 100644 --- a/api/types/container/hostconfig_unix.go +++ b/api/types/container/hostconfig_unix.go @@ -2,23 +2,11 @@ package container -import "strings" - // IsValid indicates if an isolation technology is valid func (i Isolation) IsValid() bool { return i.IsDefault() } -// IsPrivate indicates whether container uses its private network stack. -func (n NetworkMode) IsPrivate() bool { - return !(n.IsHost() || n.IsContainer()) -} - -// IsDefault indicates whether container uses the default network stack. -func (n NetworkMode) IsDefault() bool { - return n == "default" -} - // NetworkName returns the name of the network stack. func (n NetworkMode) NetworkName() string { if n.IsBridge() { @@ -47,35 +35,7 @@ func (n NetworkMode) IsHost() bool { return n == "host" } -// IsContainer indicates whether container uses a container network stack. -func (n NetworkMode) IsContainer() bool { - parts := strings.SplitN(string(n), ":", 2) - return len(parts) > 1 && parts[0] == "container" -} - -// IsNone indicates whether container isn't using a network stack. -func (n NetworkMode) IsNone() bool { - return n == "none" -} - -// ConnectedContainer is the id of the container which network this container is connected to. -func (n NetworkMode) ConnectedContainer() string { - parts := strings.SplitN(string(n), ":", 2) - if len(parts) > 1 { - return parts[1] - } - return "" -} - // IsUserDefined indicates user-created network func (n NetworkMode) IsUserDefined() bool { return !n.IsDefault() && !n.IsBridge() && !n.IsHost() && !n.IsNone() && !n.IsContainer() } - -//UserDefined indicates user-created network -func (n NetworkMode) UserDefined() string { - if n.IsUserDefined() { - return string(n) - } - return "" -} diff --git a/api/types/container/hostconfig_windows.go b/api/types/container/hostconfig_windows.go index 0ee332ba68..469923f7e9 100644 --- a/api/types/container/hostconfig_windows.go +++ b/api/types/container/hostconfig_windows.go @@ -4,22 +4,6 @@ import ( "strings" ) -// IsDefault indicates whether container uses the default network stack. -func (n NetworkMode) IsDefault() bool { - return n == "default" -} - -// IsNone indicates whether container isn't using a network stack. -func (n NetworkMode) IsNone() bool { - return n == "none" -} - -// IsContainer indicates whether container uses a container network stack. -// Returns false as windows doesn't support this mode -func (n NetworkMode) IsContainer() bool { - return false -} - // IsBridge indicates whether container uses the bridge network stack // in windows it is given the name NAT func (n NetworkMode) IsBridge() bool { @@ -32,20 +16,9 @@ func (n NetworkMode) IsHost() bool { return false } -// IsPrivate indicates whether container uses its private network stack. -func (n NetworkMode) IsPrivate() bool { - return !(n.IsHost() || n.IsContainer()) -} - -// ConnectedContainer is the id of the container which network this container is connected to. -// Returns blank string on windows -func (n NetworkMode) ConnectedContainer() string { - return "" -} - // IsUserDefined indicates user-created network func (n NetworkMode) IsUserDefined() bool { - return !n.IsDefault() && !n.IsNone() && !n.IsBridge() + return !n.IsDefault() && !n.IsNone() && !n.IsBridge() && !n.IsContainer() } // IsHyperV indicates the use of a Hyper-V partition for isolation @@ -71,17 +44,11 @@ func (n NetworkMode) NetworkName() string { return "nat" } else if n.IsNone() { return "none" + } else if n.IsContainer() { + return "container" } else if n.IsUserDefined() { return n.UserDefined() } return "" } - -//UserDefined indicates user-created network -func (n NetworkMode) UserDefined() string { - if n.IsUserDefined() { - return string(n) - } - return "" -} diff --git a/container/container_windows.go b/container/container_windows.go index 7acc519ec0..0afed738ab 100644 --- a/container/container_windows.go +++ b/container/container_windows.go @@ -16,6 +16,7 @@ type Container struct { CommonContainer // Fields below here are platform specific. + NetworkSharedContainerID string } // ExitStatus provides exit reasons for a container. diff --git a/daemon/container_operations.go b/daemon/container_operations.go index 1c0f416fa4..72155f9785 100644 --- a/daemon/container_operations.go +++ b/daemon/container_operations.go @@ -505,12 +505,13 @@ func (daemon *Daemon) allocateNetwork(container *container.Container) error { logrus.Errorf("failed to cleanup up stale network sandbox for container %s", container.ID) } - updateSettings := false - if len(container.NetworkSettings.Networks) == 0 { - if container.Config.NetworkDisabled || container.HostConfig.NetworkMode.IsContainer() { - return nil - } + if container.Config.NetworkDisabled || container.HostConfig.NetworkMode.IsContainer() { + return nil + } + updateSettings := false + + if len(container.NetworkSettings.Networks) == 0 { daemon.updateContainerNetworkSettings(container, nil) updateSettings = true } diff --git a/daemon/container_operations_windows.go b/daemon/container_operations_windows.go index eece6e1cae..df29ee7f45 100644 --- a/daemon/container_operations_windows.go +++ b/daemon/container_operations_windows.go @@ -56,4 +56,5 @@ func setupPathsAndSandboxOptions(container *container.Container, sboxOptions *[] } func initializeNetworkingPaths(container *container.Container, nc *container.Container) { + container.NetworkSharedContainerID = nc.ID } diff --git a/daemon/start_windows.go b/daemon/start_windows.go index ff046badd9..0f9739091a 100644 --- a/daemon/start_windows.go +++ b/daemon/start_windows.go @@ -157,14 +157,17 @@ func (daemon *Daemon) getLibcontainerdCreateOptions(container *container.Contain createOptions = append(createOptions, &libcontainerd.FlushOption{IgnoreFlushesDuringBoot: !container.HasBeenStartedBefore}) createOptions = append(createOptions, hvOpts) createOptions = append(createOptions, layerOpts) - if epList != nil { - createOptions = append(createOptions, &libcontainerd.NetworkEndpointsOption{ - Endpoints: epList, - AllowUnqualifiedDNSQuery: AllowUnqualifiedDNSQuery, - DNSSearchList: dnsSearch, - }) - } + var networkSharedContainerID string + if container.HostConfig.NetworkMode.IsContainer() { + networkSharedContainerID = container.NetworkSharedContainerID + } + createOptions = append(createOptions, &libcontainerd.NetworkEndpointsOption{ + Endpoints: epList, + AllowUnqualifiedDNSQuery: AllowUnqualifiedDNSQuery, + DNSSearchList: dnsSearch, + NetworkSharedContainerID: networkSharedContainerID, + }) return createOptions, nil } diff --git a/libcontainerd/client_windows.go b/libcontainerd/client_windows.go index 30b3b6c4cc..cf55ac2d4d 100644 --- a/libcontainerd/client_windows.go +++ b/libcontainerd/client_windows.go @@ -170,6 +170,7 @@ func (clnt *client) Create(containerID string, checkpoint string, checkpointDir if n.DNSSearchList != nil { configuration.DNSSearchList = strings.Join(n.DNSSearchList, ",") } + configuration.NetworkSharedContainerName = n.NetworkSharedContainerID continue } if c, ok := option.(*CredentialsOption); ok { diff --git a/libcontainerd/types_windows.go b/libcontainerd/types_windows.go index d0389cc6f5..cf4d640fa1 100644 --- a/libcontainerd/types_windows.go +++ b/libcontainerd/types_windows.go @@ -60,6 +60,7 @@ type NetworkEndpointsOption struct { Endpoints []string AllowUnqualifiedDNSQuery bool DNSSearchList []string + NetworkSharedContainerID string } // CredentialsOption is a CreateOption that indicates the credentials from diff --git a/runconfig/hostconfig.go b/runconfig/hostconfig.go index a95fac6823..2fd54f6937 100644 --- a/runconfig/hostconfig.go +++ b/runconfig/hostconfig.go @@ -2,7 +2,9 @@ package runconfig import ( "encoding/json" + "fmt" "io" + "strings" "github.com/docker/docker/api/types/container" ) @@ -32,3 +34,47 @@ func SetDefaultNetModeIfBlank(hc *container.HostConfig) { } } } + +// ValidateNetContainerMode ensures that the various combinations of requested +// network settings wrt container mode are valid. +func ValidateNetContainerMode(c *container.Config, hc *container.HostConfig) error { + // We may not be passed a host config, such as in the case of docker commit + if hc == nil { + return nil + } + parts := strings.Split(string(hc.NetworkMode), ":") + if parts[0] == "container" { + if len(parts) < 2 || parts[1] == "" { + return fmt.Errorf("--net: invalid net mode: invalid container format container:") + } + } + + if hc.NetworkMode.IsContainer() && c.Hostname != "" { + return ErrConflictNetworkHostname + } + + if hc.NetworkMode.IsContainer() && len(hc.Links) > 0 { + return ErrConflictContainerNetworkAndLinks + } + + if hc.NetworkMode.IsContainer() && len(hc.DNS) > 0 { + return ErrConflictNetworkAndDNS + } + + if hc.NetworkMode.IsContainer() && len(hc.ExtraHosts) > 0 { + return ErrConflictNetworkHosts + } + + if (hc.NetworkMode.IsContainer() || hc.NetworkMode.IsHost()) && c.MacAddress != "" { + return ErrConflictContainerNetworkAndMac + } + + if hc.NetworkMode.IsContainer() && (len(hc.PortBindings) > 0 || hc.PublishAllPorts == true) { + return ErrConflictNetworkPublishPorts + } + + if hc.NetworkMode.IsContainer() && len(c.ExposedPorts) > 0 { + return ErrConflictNetworkExposePorts + } + return nil +} diff --git a/runconfig/hostconfig_unix.go b/runconfig/hostconfig_unix.go index 6e2b7f5ff7..b65f149679 100644 --- a/runconfig/hostconfig_unix.go +++ b/runconfig/hostconfig_unix.go @@ -5,7 +5,6 @@ package runconfig import ( "fmt" "runtime" - "strings" "github.com/docker/docker/api/types/container" "github.com/docker/docker/pkg/sysinfo" @@ -30,15 +29,10 @@ func ValidateNetMode(c *container.Config, hc *container.HostConfig) error { if hc == nil { return nil } - parts := strings.Split(string(hc.NetworkMode), ":") - if parts[0] == "container" { - if len(parts) < 2 || parts[1] == "" { - return fmt.Errorf("--net: invalid net mode: invalid container format container:") - } - } - if hc.NetworkMode.IsContainer() && c.Hostname != "" { - return ErrConflictNetworkHostname + err := ValidateNetContainerMode(c, hc) + if err != nil { + return err } if hc.UTSMode.IsHost() && c.Hostname != "" { @@ -49,29 +43,6 @@ func ValidateNetMode(c *container.Config, hc *container.HostConfig) error { return ErrConflictHostNetworkAndLinks } - if hc.NetworkMode.IsContainer() && len(hc.Links) > 0 { - return ErrConflictContainerNetworkAndLinks - } - - if hc.NetworkMode.IsContainer() && len(hc.DNS) > 0 { - return ErrConflictNetworkAndDNS - } - - if hc.NetworkMode.IsContainer() && len(hc.ExtraHosts) > 0 { - return ErrConflictNetworkHosts - } - - if (hc.NetworkMode.IsContainer() || hc.NetworkMode.IsHost()) && c.MacAddress != "" { - return ErrConflictContainerNetworkAndMac - } - - if hc.NetworkMode.IsContainer() && (len(hc.PortBindings) > 0 || hc.PublishAllPorts == true) { - return ErrConflictNetworkPublishPorts - } - - if hc.NetworkMode.IsContainer() && len(c.ExposedPorts) > 0 { - return ErrConflictNetworkExposePorts - } return nil } diff --git a/runconfig/hostconfig_windows.go b/runconfig/hostconfig_windows.go index 91bd6dcc3c..d3150ac06d 100644 --- a/runconfig/hostconfig_windows.go +++ b/runconfig/hostconfig_windows.go @@ -2,7 +2,6 @@ package runconfig import ( "fmt" - "strings" "github.com/docker/docker/api/types/container" "github.com/docker/docker/pkg/sysinfo" @@ -25,10 +24,16 @@ func ValidateNetMode(c *container.Config, hc *container.HostConfig) error { if hc == nil { return nil } - parts := strings.Split(string(hc.NetworkMode), ":") - if len(parts) > 1 { - return fmt.Errorf("invalid --net: %s", hc.NetworkMode) + + err := ValidateNetContainerMode(c, hc) + if err != nil { + return err } + + if hc.NetworkMode.IsContainer() && hc.Isolation.IsHyperV() { + return fmt.Errorf("net mode --net=container: unsupported for hyperv isolation") + } + return nil }