// DisconnectFromNetwork disconnects container from network n. func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, n libnetwork.Network, force bool) error { if container.HostConfig.NetworkMode.IsHost() && containertypes.NetworkMode(n.Type()).IsHost() { return runconfig.ErrConflictHostNetwork } if !container.Running { if container.RemovalInProgress || container.Dead { return errRemovalContainer(container.ID) } if _, ok := container.NetworkSettings.Networks[n.Name()]; ok { delete(container.NetworkSettings.Networks, n.Name()) } else { return fmt.Errorf("container %s is not connected to the network %s", container.ID, n.Name()) } } else { if err := disconnectFromNetwork(container, n, false); err != nil { return err } } if err := container.ToDiskLocking(); err != nil { return fmt.Errorf("Error saving container to disk: %v", err) } attributes := map[string]string{ "container": container.ID, } daemon.LogNetworkEventWithAttributes(n, "disconnect", attributes) return nil }
func buildNetworkResource(nw libnetwork.Network) *types.NetworkResource { r := &types.NetworkResource{} if nw == nil { return r } r.Name = nw.Name() r.ID = nw.ID() r.Scope = nw.Info().Scope() r.Driver = nw.Type() r.Containers = make(map[string]types.EndpointResource) r.Labels = nw.Info().Labels() buildIpamResources(r, nw) epl := nw.Endpoints() for _, e := range epl { sb := e.Info().Sandbox() if sb == nil { continue } r.Containers[sb.ContainerID()] = buildEndpointResource(e) } return r }
func buildNetworkResource(nw libnetwork.Network) *types.NetworkResource { r := &types.NetworkResource{} if nw == nil { return r } r.Name = nw.Name() r.ID = nw.ID() r.Scope = nw.Info().Scope() r.Driver = nw.Type() r.EnableIPv6 = nw.Info().IPv6Enabled() r.Internal = nw.Info().Internal() r.Options = nw.Info().DriverOptions() r.Containers = make(map[string]types.EndpointResource) buildIpamResources(r, nw) r.Internal = nw.Info().Internal() epl := nw.Endpoints() for _, e := range epl { ei := e.Info() if ei == nil { continue } sb := ei.Sandbox() if sb == nil { continue } r.Containers[sb.ContainerID()] = buildEndpointResource(e) } return r }
func buildNetworkResource(nw libnetwork.Network) *types.NetworkResource { r := &types.NetworkResource{} if nw == nil { return r } info := nw.Info() r.Name = nw.Name() r.ID = nw.ID() r.Scope = info.Scope() r.Driver = nw.Type() r.EnableIPv6 = info.IPv6Enabled() r.Internal = info.Internal() r.Options = info.DriverOptions() r.Containers = make(map[string]types.EndpointResource) buildIpamResources(r, info) r.Internal = info.Internal() r.Labels = info.Labels() epl := nw.Endpoints() for _, e := range epl { ei := e.Info() if ei == nil { continue } sb := ei.Sandbox() key := "ep-" + e.ID() if sb != nil { key = sb.ContainerID() } r.Containers[key] = buildEndpointResource(e) } return r }
func (container *Container) disconnectFromNetwork(n libnetwork.Network) error { var ( ep libnetwork.Endpoint sbox libnetwork.Sandbox ) s := func(current libnetwork.Endpoint) bool { if sb := current.Info().Sandbox(); sb != nil { if sb.ContainerID() == container.ID { ep = current sbox = sb return true } } return false } n.WalkEndpoints(s) if ep == nil { return fmt.Errorf("container %s is not connected to the network", container.ID) } if err := ep.Leave(sbox); err != nil { return fmt.Errorf("container %s failed to leave network %s: %v", container.ID, n.Name(), err) } if err := ep.Delete(); err != nil { return fmt.Errorf("endpoint delete failed for container %s on network %s: %v", container.ID, n.Name(), err) } delete(container.NetworkSettings.Networks, n.Name()) return nil }
func (daemon *Daemon) updateNetworkConfig(container *container.Container, n libnetwork.Network, endpointConfig *networktypes.EndpointSettings, updateSettings bool) error { if !containertypes.NetworkMode(n.Name()).IsUserDefined() { if hasUserDefinedIPAddress(endpointConfig) && !enableIPOnPredefinedNetwork() { return runconfig.ErrUnsupportedNetworkAndIP } if endpointConfig != nil && len(endpointConfig.Aliases) > 0 && !container.EnableServiceDiscoveryOnDefaultNetwork() { return runconfig.ErrUnsupportedNetworkAndAlias } } else { addShortID := true shortID := stringid.TruncateID(container.ID) for _, alias := range endpointConfig.Aliases { if alias == shortID { addShortID = false break } } if addShortID { endpointConfig.Aliases = append(endpointConfig.Aliases, shortID) } } if err := validateNetworkingConfig(n, endpointConfig); err != nil { return err } if updateSettings { if err := daemon.updateNetworkSettings(container, n, endpointConfig); err != nil { return err } } return nil }
func (daemon *Daemon) disconnectFromNetwork(container *container.Container, n libnetwork.Network, force bool) error { var ( ep libnetwork.Endpoint sbox libnetwork.Sandbox ) s := func(current libnetwork.Endpoint) bool { epInfo := current.Info() if epInfo == nil { return false } if sb := epInfo.Sandbox(); sb != nil { if sb.ContainerID() == container.ID { ep = current sbox = sb return true } } return false } n.WalkEndpoints(s) if ep == nil && force { epName := strings.TrimPrefix(container.Name, "/") ep, err := n.EndpointByName(epName) if err != nil { return err } return ep.Delete(force) } if ep == nil { return fmt.Errorf("container %s is not connected to network %s", container.ID, n.Name()) } if err := ep.Leave(sbox); err != nil { return fmt.Errorf("container %s failed to leave network %s: %v", container.ID, n.Name(), err) } container.NetworkSettings.Ports = getPortMapInfo(sbox) if err := ep.Delete(false); err != nil { return fmt.Errorf("endpoint delete failed for container %s on network %s: %v", container.ID, n.Name(), err) } delete(container.NetworkSettings.Networks, n.Name()) if daemon.clusterProvider != nil && n.Info().Dynamic() && !container.Managed { if err := daemon.clusterProvider.DetachNetwork(n.Name(), container.ID); err != nil { logrus.Warnf("error detaching from network %s: %v", n.Name(), err) if err := daemon.clusterProvider.DetachNetwork(n.ID(), container.ID); err != nil { logrus.Warnf("error detaching from network %s: %v", n.ID(), err) } } } return nil }
// LogNetworkEventWithAttributes generates an event related to a network with specific given attributes. func (daemon *Daemon) LogNetworkEventWithAttributes(nw libnetwork.Network, action string, attributes map[string]string) { attributes["name"] = nw.Name() attributes["type"] = nw.Type() actor := events.Actor{ ID: nw.ID(), Attributes: attributes, } daemon.EventsService.Log(action, events.NetworkEventType, actor) }
// updateContainerNetworkSettings update the network settings func (daemon *Daemon) updateContainerNetworkSettings(container *container.Container, endpointsConfig map[string]*networktypes.EndpointSettings) error { var ( n libnetwork.Network err error ) // TODO Windows: Remove this once TP4 builds are not supported // Windows TP4 build don't support libnetwork and in that case // daemon.netController will be nil if daemon.netController == nil { return nil } mode := container.HostConfig.NetworkMode if container.Config.NetworkDisabled || mode.IsContainer() { return nil } networkName := mode.NetworkName() if mode.IsDefault() { networkName = daemon.netController.Config().Daemon.DefaultNetwork } if mode.IsUserDefined() { n, err = daemon.FindNetwork(networkName) if err != nil { return err } networkName = n.Name() } if container.NetworkSettings == nil { container.NetworkSettings = &network.Settings{} } if len(endpointsConfig) > 0 { container.NetworkSettings.Networks = endpointsConfig } if container.NetworkSettings.Networks == nil { container.NetworkSettings.Networks = make(map[string]*networktypes.EndpointSettings) container.NetworkSettings.Networks[networkName] = new(networktypes.EndpointSettings) } if !mode.IsUserDefined() { return nil } // Make sure to internally store the per network endpoint config by network name if _, ok := container.NetworkSettings.Networks[networkName]; ok { return nil } if nwConfig, ok := container.NetworkSettings.Networks[n.ID()]; ok { container.NetworkSettings.Networks[networkName] = nwConfig delete(container.NetworkSettings.Networks, n.ID()) return nil } return nil }
func (container *Container) updateJoinInfo(n libnetwork.Network, ep libnetwork.Endpoint) error { epInfo := ep.Info() if epInfo == nil { // It is not an error to get an empty endpoint info return nil } container.NetworkSettings.Networks[n.Name()].Gateway = epInfo.Gateway().String() if epInfo.GatewayIPv6().To16() != nil { container.NetworkSettings.Networks[n.Name()].IPv6Gateway = epInfo.GatewayIPv6().String() } return nil }
// BuildJoinOptions builds endpoint Join options from a given network. func (container *Container) BuildJoinOptions(n libnetwork.Network) ([]libnetwork.EndpointOption, error) { var joinOptions []libnetwork.EndpointOption if epConfig, ok := container.NetworkSettings.Networks[n.Name()]; ok { for _, str := range epConfig.Links { name, alias, err := runconfigopts.ParseLink(str) if err != nil { return nil, err } joinOptions = append(joinOptions, libnetwork.CreateOptionAlias(name, alias)) } } return joinOptions, nil }
func (daemon *Daemon) updateNetworkSettings(container *container.Container, n libnetwork.Network) error { if container.NetworkSettings == nil { container.NetworkSettings = &network.Settings{Networks: make(map[string]*networktypes.EndpointSettings)} } if !container.HostConfig.NetworkMode.IsHost() && containertypes.NetworkMode(n.Type()).IsHost() { return runconfig.ErrConflictHostNetwork } for s := range container.NetworkSettings.Networks { sn, err := daemon.FindNetwork(s) if err != nil { continue } if sn.Name() == n.Name() { // Avoid duplicate config return nil } if !containertypes.NetworkMode(sn.Type()).IsPrivate() || !containertypes.NetworkMode(n.Type()).IsPrivate() { return runconfig.ErrConflictSharedNetwork } if containertypes.NetworkMode(sn.Name()).IsNone() || containertypes.NetworkMode(n.Name()).IsNone() { return runconfig.ErrConflictNoNetwork } } if _, ok := container.NetworkSettings.Networks[n.Name()]; !ok { container.NetworkSettings.Networks[n.Name()] = new(networktypes.EndpointSettings) } return nil }
// updateContainerNetworkSettings update the network settings func (daemon *Daemon) updateContainerNetworkSettings(container *container.Container, endpointsConfig map[string]*networktypes.EndpointSettings) error { var ( n libnetwork.Network err error ) mode := container.HostConfig.NetworkMode if container.Config.NetworkDisabled || mode.IsContainer() { return nil } networkName := mode.NetworkName() if mode.IsDefault() { networkName = daemon.netController.Config().Daemon.DefaultNetwork } if mode.IsUserDefined() { n, err = daemon.FindNetwork(networkName) if err != nil { return err } if !container.Managed && n.Info().Dynamic() { return errClusterNetworkOnRun(networkName) } networkName = n.Name() } if container.NetworkSettings == nil { container.NetworkSettings = &network.Settings{} } if len(endpointsConfig) > 0 { container.NetworkSettings.Networks = endpointsConfig } if container.NetworkSettings.Networks == nil { container.NetworkSettings.Networks = make(map[string]*networktypes.EndpointSettings) container.NetworkSettings.Networks[networkName] = new(networktypes.EndpointSettings) } if !mode.IsUserDefined() { return nil } // Make sure to internally store the per network endpoint config by network name if _, ok := container.NetworkSettings.Networks[networkName]; ok { return nil } if nwConfig, ok := container.NetworkSettings.Networks[n.ID()]; ok { container.NetworkSettings.Networks[networkName] = nwConfig delete(container.NetworkSettings.Networks, n.ID()) return nil } return nil }
func (n *networkRouter) buildNetworkResource(nw libnetwork.Network) *types.NetworkResource { r := &types.NetworkResource{} if nw == nil { return r } info := nw.Info() r.Name = nw.Name() r.ID = nw.ID() r.Created = info.Created() r.Scope = info.Scope() if n.clusterProvider.IsManager() { if _, err := n.clusterProvider.GetNetwork(nw.Name()); err == nil { r.Scope = "swarm" } } else if info.Dynamic() { r.Scope = "swarm" } r.Driver = nw.Type() r.EnableIPv6 = info.IPv6Enabled() r.Internal = info.Internal() r.Attachable = info.Attachable() r.Options = info.DriverOptions() r.Containers = make(map[string]types.EndpointResource) buildIpamResources(r, info) r.Labels = info.Labels() peers := info.Peers() if len(peers) != 0 { r.Peers = buildPeerInfoResources(peers) } epl := nw.Endpoints() for _, e := range epl { ei := e.Info() if ei == nil { continue } sb := ei.Sandbox() tmpID := e.ID() key := "ep-" + tmpID if sb != nil { key = sb.ContainerID() } r.Containers[key] = buildEndpointResource(tmpID, e.Name(), ei) } return r }
func buildNetworkResource(nw libnetwork.Network) *networkResource { r := &networkResource{} if nw != nil { r.Name = nw.Name() r.ID = nw.ID() r.Type = nw.Type() epl := nw.Endpoints() r.Endpoints = make([]*endpointResource, 0, len(epl)) for _, e := range epl { epr := buildEndpointResource(e) r.Endpoints = append(r.Endpoints, epr) } } return r }
func disconnectFromNetwork(container *container.Container, n libnetwork.Network, force bool) error { var ( ep libnetwork.Endpoint sbox libnetwork.Sandbox ) s := func(current libnetwork.Endpoint) bool { epInfo := current.Info() if epInfo == nil { return false } if sb := epInfo.Sandbox(); sb != nil { if sb.ContainerID() == container.ID { ep = current sbox = sb return true } } return false } n.WalkEndpoints(s) if ep == nil && force { epName := strings.TrimPrefix(container.Name, "/") ep, err := n.EndpointByName(epName) if err != nil { return err } return ep.Delete(force) } if ep == nil { return fmt.Errorf("container %s is not connected to the network", container.ID) } if err := ep.Leave(sbox); err != nil { return fmt.Errorf("container %s failed to leave network %s: %v", container.ID, n.Name(), err) } container.NetworkSettings.Ports = getPortMapInfo(sbox) if err := ep.Delete(false); err != nil { return fmt.Errorf("endpoint delete failed for container %s on network %s: %v", container.ID, n.Name(), err) } delete(container.NetworkSettings.Networks, n.Name()) return nil }
func (container *Container) disconnectFromNetwork(n libnetwork.Network, updateSettings bool) error { var ( ep libnetwork.Endpoint sbox libnetwork.Sandbox ) s := func(current libnetwork.Endpoint) bool { if sb := current.Info().Sandbox(); sb != nil { if sb.ContainerID() == container.ID { ep = current sbox = sb return true } } return false } n.WalkEndpoints(s) if ep == nil { return fmt.Errorf("could not locate network endpoint for container %s", container.ID) } if err := ep.Leave(sbox); err != nil { return fmt.Errorf("container %s failed to leave network %s: %v", container.ID, n.Name(), err) } if err := ep.Delete(); err != nil { return fmt.Errorf("endpoint delete failed for container %s on network %s: %v", container.ID, n.Name(), err) } if updateSettings { networks := container.NetworkSettings.Networks for i, s := range networks { sn, err := container.daemon.FindNetwork(s) if err != nil { continue } if sn.Name() == n.Name() { networks = append(networks[:i], networks[i+1:]...) container.NetworkSettings.Networks = networks break } } } return nil }
func (container *Container) updateNetworkSettings(n libnetwork.Network) error { if container.NetworkSettings == nil { container.NetworkSettings = &network.Settings{Networks: make(map[string]*network.EndpointSettings)} } for s := range container.NetworkSettings.Networks { sn, err := container.daemon.FindNetwork(s) if err != nil { continue } if sn.Name() == n.Name() { // Avoid duplicate config return nil } if !runconfig.NetworkMode(sn.Type()).IsPrivate() || !runconfig.NetworkMode(n.Type()).IsPrivate() { return runconfig.ErrConflictSharedNetwork } if runconfig.NetworkMode(sn.Name()).IsNone() || runconfig.NetworkMode(n.Name()).IsNone() { return runconfig.ErrConflictNoNetwork } } container.NetworkSettings.Networks[n.Name()] = new(network.EndpointSettings) return nil }
func (container *Container) updateNetworkSettings(n libnetwork.Network) error { if container.NetworkSettings == nil { container.NetworkSettings = &network.Settings{Networks: []string{}} } settings := container.NetworkSettings for _, s := range settings.Networks { sn, err := container.daemon.FindNetwork(s) if err != nil { continue } if sn.Name() == n.Name() { // Avoid duplicate config return nil } if !runconfig.NetworkMode(sn.Type()).IsPrivate() || !runconfig.NetworkMode(n.Type()).IsPrivate() { return runconfig.ErrConflictSharedNetwork } if runconfig.NetworkMode(sn.Name()).IsNone() || runconfig.NetworkMode(n.Name()).IsNone() { return runconfig.ErrConflictNoNetwork } } settings.Networks = append(settings.Networks, n.Name()) return nil }
// BuildCreateEndpointOptions builds endpoint options from a given network. func (container *Container) BuildCreateEndpointOptions(n libnetwork.Network, epConfig *networktypes.EndpointSettings, sb libnetwork.Sandbox, daemonDNS []string) ([]libnetwork.EndpointOption, error) { var ( bindings = make(nat.PortMap) pbList []types.PortBinding exposeList []types.TransportPort createOptions []libnetwork.EndpointOption ) defaultNetName := runconfig.DefaultDaemonNetworkMode().NetworkName() if (!container.EnableServiceDiscoveryOnDefaultNetwork() && n.Name() == defaultNetName) || container.NetworkSettings.IsAnonymousEndpoint { createOptions = append(createOptions, libnetwork.CreateOptionAnonymous()) } if epConfig != nil { ipam := epConfig.IPAMConfig if ipam != nil && (ipam.IPv4Address != "" || ipam.IPv6Address != "" || len(ipam.LinkLocalIPs) > 0) { var ipList []net.IP for _, ips := range ipam.LinkLocalIPs { if ip := net.ParseIP(ips); ip != nil { ipList = append(ipList, ip) } } createOptions = append(createOptions, libnetwork.CreateOptionIpam(net.ParseIP(ipam.IPv4Address), net.ParseIP(ipam.IPv6Address), ipList, nil)) } for _, alias := range epConfig.Aliases { createOptions = append(createOptions, libnetwork.CreateOptionMyAlias(alias)) } } if container.NetworkSettings.Service != nil { svcCfg := container.NetworkSettings.Service var vip string if svcCfg.VirtualAddresses[n.ID()] != nil { vip = svcCfg.VirtualAddresses[n.ID()].IPv4 } var portConfigs []*libnetwork.PortConfig for _, portConfig := range svcCfg.ExposedPorts { portConfigs = append(portConfigs, &libnetwork.PortConfig{ Name: portConfig.Name, Protocol: libnetwork.PortConfig_Protocol(portConfig.Protocol), TargetPort: portConfig.TargetPort, PublishedPort: portConfig.PublishedPort, }) } createOptions = append(createOptions, libnetwork.CreateOptionService(svcCfg.Name, svcCfg.ID, net.ParseIP(vip), portConfigs, svcCfg.Aliases[n.ID()])) } if !containertypes.NetworkMode(n.Name()).IsUserDefined() { createOptions = append(createOptions, libnetwork.CreateOptionDisableResolution()) } // configs that are applicable only for the endpoint in the network // to which container was connected to on docker run. // Ideally all these network-specific endpoint configurations must be moved under // container.NetworkSettings.Networks[n.Name()] if n.Name() == container.HostConfig.NetworkMode.NetworkName() || (n.Name() == defaultNetName && container.HostConfig.NetworkMode.IsDefault()) { if container.Config.MacAddress != "" { mac, err := net.ParseMAC(container.Config.MacAddress) if err != nil { return nil, err } genericOption := options.Generic{ netlabel.MacAddress: mac, } createOptions = append(createOptions, libnetwork.EndpointOptionGeneric(genericOption)) } } // Port-mapping rules belong to the container & applicable only to non-internal networks portmaps := GetSandboxPortMapInfo(sb) if n.Info().Internal() || len(portmaps) > 0 { return createOptions, nil } if container.HostConfig.PortBindings != nil { for p, b := range container.HostConfig.PortBindings { bindings[p] = []nat.PortBinding{} for _, bb := range b { bindings[p] = append(bindings[p], nat.PortBinding{ HostIP: bb.HostIP, HostPort: bb.HostPort, }) } } } portSpecs := container.Config.ExposedPorts ports := make([]nat.Port, len(portSpecs)) var i int for p := range portSpecs { ports[i] = p i++ } nat.SortPortMap(ports, bindings) for _, port := range ports { expose := types.TransportPort{} expose.Proto = types.ParseProtocol(port.Proto()) expose.Port = uint16(port.Int()) exposeList = append(exposeList, expose) pb := types.PortBinding{Port: expose.Port, Proto: expose.Proto} binding := bindings[port] for i := 0; i < len(binding); i++ { pbCopy := pb.GetCopy() newP, err := nat.NewPort(nat.SplitProtoPort(binding[i].HostPort)) var portStart, portEnd int if err == nil { portStart, portEnd, err = newP.Range() } if err != nil { return nil, fmt.Errorf("Error parsing HostPort value(%s):%v", binding[i].HostPort, err) } pbCopy.HostPort = uint16(portStart) pbCopy.HostPortEnd = uint16(portEnd) pbCopy.HostIP = net.ParseIP(binding[i].HostIP) pbList = append(pbList, pbCopy) } if container.HostConfig.PublishAllPorts && len(binding) == 0 { pbList = append(pbList, pb) } } var dns []string if len(container.HostConfig.DNS) > 0 { dns = container.HostConfig.DNS } else if len(daemonDNS) > 0 { dns = daemonDNS } if len(dns) > 0 { createOptions = append(createOptions, libnetwork.CreateOptionDNS(dns)) } createOptions = append(createOptions, libnetwork.CreateOptionPortMapping(pbList), libnetwork.CreateOptionExposedPorts(exposeList)) return createOptions, nil }
// BuildEndpointInfo sets endpoint-related fields on container.NetworkSettings based on the provided network and endpoint. func (container *Container) BuildEndpointInfo(n libnetwork.Network, ep libnetwork.Endpoint) error { if ep == nil { return errInvalidEndpoint } networkSettings := container.NetworkSettings if networkSettings == nil { return errInvalidNetwork } epInfo := ep.Info() if epInfo == nil { // It is not an error to get an empty endpoint info return nil } if _, ok := networkSettings.Networks[n.Name()]; !ok { networkSettings.Networks[n.Name()] = &network.EndpointSettings{ EndpointSettings: &networktypes.EndpointSettings{}, } } networkSettings.Networks[n.Name()].NetworkID = n.ID() networkSettings.Networks[n.Name()].EndpointID = ep.ID() iface := epInfo.Iface() if iface == nil { return nil } if iface.MacAddress() != nil { networkSettings.Networks[n.Name()].MacAddress = iface.MacAddress().String() } if iface.Address() != nil { ones, _ := iface.Address().Mask.Size() networkSettings.Networks[n.Name()].IPAddress = iface.Address().IP.String() networkSettings.Networks[n.Name()].IPPrefixLen = ones } if iface.AddressIPv6() != nil && iface.AddressIPv6().IP.To16() != nil { onesv6, _ := iface.AddressIPv6().Mask.Size() networkSettings.Networks[n.Name()].GlobalIPv6Address = iface.AddressIPv6().IP.String() networkSettings.Networks[n.Name()].GlobalIPv6PrefixLen = onesv6 } return nil }
// BuildCreateEndpointOptions builds endpoint options from a given network. func (container *Container) BuildCreateEndpointOptions(n libnetwork.Network, epConfig *network.EndpointSettings, sb libnetwork.Sandbox) ([]libnetwork.EndpointOption, error) { var ( portSpecs = make(nat.PortSet) bindings = make(nat.PortMap) pbList []types.PortBinding exposeList []types.TransportPort createOptions []libnetwork.EndpointOption ) if n.Name() == "bridge" || container.NetworkSettings.IsAnonymousEndpoint { createOptions = append(createOptions, libnetwork.CreateOptionAnonymous()) } if epConfig != nil { ipam := epConfig.IPAMConfig if ipam != nil && (ipam.IPv4Address != "" || ipam.IPv6Address != "") { createOptions = append(createOptions, libnetwork.CreateOptionIpam(net.ParseIP(ipam.IPv4Address), net.ParseIP(ipam.IPv6Address), nil)) } for _, alias := range epConfig.Aliases { createOptions = append(createOptions, libnetwork.CreateOptionMyAlias(alias)) } } if !containertypes.NetworkMode(n.Name()).IsUserDefined() { createOptions = append(createOptions, libnetwork.CreateOptionDisableResolution()) } // configs that are applicable only for the endpoint in the network // to which container was connected to on docker run. // Ideally all these network-specific endpoint configurations must be moved under // container.NetworkSettings.Networks[n.Name()] if n.Name() == container.HostConfig.NetworkMode.NetworkName() || (n.Name() == "bridge" && container.HostConfig.NetworkMode.IsDefault()) { if container.Config.MacAddress != "" { mac, err := net.ParseMAC(container.Config.MacAddress) if err != nil { return nil, err } genericOption := options.Generic{ netlabel.MacAddress: mac, } createOptions = append(createOptions, libnetwork.EndpointOptionGeneric(genericOption)) } } // Port-mapping rules belong to the container & applicable only to non-internal networks portmaps := getSandboxPortMapInfo(sb) if n.Info().Internal() || len(portmaps) > 0 { return createOptions, nil } if container.Config.ExposedPorts != nil { portSpecs = container.Config.ExposedPorts } if container.HostConfig.PortBindings != nil { for p, b := range container.HostConfig.PortBindings { bindings[p] = []nat.PortBinding{} for _, bb := range b { bindings[p] = append(bindings[p], nat.PortBinding{ HostIP: bb.HostIP, HostPort: bb.HostPort, }) } } } ports := make([]nat.Port, len(portSpecs)) var i int for p := range portSpecs { ports[i] = p i++ } nat.SortPortMap(ports, bindings) for _, port := range ports { expose := types.TransportPort{} expose.Proto = types.ParseProtocol(port.Proto()) expose.Port = uint16(port.Int()) exposeList = append(exposeList, expose) pb := types.PortBinding{Port: expose.Port, Proto: expose.Proto} binding := bindings[port] for i := 0; i < len(binding); i++ { pbCopy := pb.GetCopy() newP, err := nat.NewPort(nat.SplitProtoPort(binding[i].HostPort)) var portStart, portEnd int if err == nil { portStart, portEnd, err = newP.Range() } if err != nil { return nil, derr.ErrorCodeHostPort.WithArgs(binding[i].HostPort, err) } pbCopy.HostPort = uint16(portStart) pbCopy.HostPortEnd = uint16(portEnd) pbCopy.HostIP = net.ParseIP(binding[i].HostIP) pbList = append(pbList, pbCopy) } if container.HostConfig.PublishAllPorts && len(binding) == 0 { pbList = append(pbList, pb) } } createOptions = append(createOptions, libnetwork.CreateOptionPortMapping(pbList), libnetwork.CreateOptionExposedPorts(exposeList)) return createOptions, nil }
// updateContainerNetworkSettings update the network settings func (daemon *Daemon) updateContainerNetworkSettings(container *container.Container, endpointsConfig map[string]*networktypes.EndpointSettings) { var n libnetwork.Network mode := container.HostConfig.NetworkMode if container.Config.NetworkDisabled || mode.IsContainer() { return } networkName := mode.NetworkName() if mode.IsDefault() { networkName = daemon.netController.Config().Daemon.DefaultNetwork } if mode.IsUserDefined() { var err error n, err = daemon.FindNetwork(networkName) if err == nil { networkName = n.Name() } } if container.NetworkSettings == nil { container.NetworkSettings = &network.Settings{} } if len(endpointsConfig) > 0 { if container.NetworkSettings.Networks == nil { container.NetworkSettings.Networks = make(map[string]*network.EndpointSettings) } for name, epConfig := range endpointsConfig { container.NetworkSettings.Networks[name] = &network.EndpointSettings{ EndpointSettings: epConfig, } } } if container.NetworkSettings.Networks == nil { container.NetworkSettings.Networks = make(map[string]*network.EndpointSettings) container.NetworkSettings.Networks[networkName] = &network.EndpointSettings{ EndpointSettings: &networktypes.EndpointSettings{}, } } // Convert any settings added by client in default name to // engine's default network name key if mode.IsDefault() { if nConf, ok := container.NetworkSettings.Networks[mode.NetworkName()]; ok { container.NetworkSettings.Networks[networkName] = nConf delete(container.NetworkSettings.Networks, mode.NetworkName()) } } if !mode.IsUserDefined() { return } // Make sure to internally store the per network endpoint config by network name if _, ok := container.NetworkSettings.Networks[networkName]; ok { return } if n != nil { if nwConfig, ok := container.NetworkSettings.Networks[n.ID()]; ok { container.NetworkSettings.Networks[networkName] = nwConfig delete(container.NetworkSettings.Networks, n.ID()) return } } }
func (daemon *Daemon) initNetworkController(config *Config, activeSandboxes map[string]interface{}) (libnetwork.NetworkController, error) { netOptions, err := daemon.networkOptions(config, nil, nil) if err != nil { return nil, err } controller, err := libnetwork.New(netOptions...) if err != nil { return nil, fmt.Errorf("error obtaining controller instance: %v", err) } hnsresponse, err := hcsshim.HNSListNetworkRequest("GET", "", "") if err != nil { return nil, err } // Remove networks not present in HNS for _, v := range controller.Networks() { options := v.Info().DriverOptions() hnsid := options[winlibnetwork.HNSID] found := false for _, v := range hnsresponse { if v.Id == hnsid { found = true break } } if !found { // global networks should not be deleted by local HNS if v.Info().Scope() != datastore.GlobalScope { err = v.Delete() if err != nil { logrus.Errorf("Error occurred when removing network %v", err) } } } } _, err = controller.NewNetwork("null", "none", "", libnetwork.NetworkOptionPersist(false)) if err != nil { return nil, err } defaultNetworkExists := false if network, err := controller.NetworkByName(runconfig.DefaultDaemonNetworkMode().NetworkName()); err == nil { options := network.Info().DriverOptions() for _, v := range hnsresponse { if options[winlibnetwork.HNSID] == v.Id { defaultNetworkExists = true break } } } // discover and add HNS networks to windows // network that exist are removed and added again for _, v := range hnsresponse { var n libnetwork.Network s := func(current libnetwork.Network) bool { options := current.Info().DriverOptions() if options[winlibnetwork.HNSID] == v.Id { n = current return true } return false } controller.WalkNetworks(s) if n != nil { // global networks should not be deleted by local HNS if n.Info().Scope() == datastore.GlobalScope { continue } v.Name = n.Name() // This will not cause network delete from HNS as the network // is not yet populated in the libnetwork windows driver n.Delete() } netOption := map[string]string{ winlibnetwork.NetworkName: v.Name, winlibnetwork.HNSID: v.Id, } v4Conf := []*libnetwork.IpamConf{} for _, subnet := range v.Subnets { ipamV4Conf := libnetwork.IpamConf{} ipamV4Conf.PreferredPool = subnet.AddressPrefix ipamV4Conf.Gateway = subnet.GatewayAddress v4Conf = append(v4Conf, &ipamV4Conf) } name := v.Name // If there is no nat network create one from the first NAT network // encountered if !defaultNetworkExists && runconfig.DefaultDaemonNetworkMode() == containertypes.NetworkMode(strings.ToLower(v.Type)) { name = runconfig.DefaultDaemonNetworkMode().NetworkName() defaultNetworkExists = true } v6Conf := []*libnetwork.IpamConf{} _, err := controller.NewNetwork(strings.ToLower(v.Type), name, "", libnetwork.NetworkOptionGeneric(options.Generic{ netlabel.GenericData: netOption, }), libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf, nil), ) if err != nil { logrus.Errorf("Error occurred when creating network %v", err) } } if !config.DisableBridge { // Initialize default driver "bridge" if err := initBridgeDriver(controller, config); err != nil { return nil, err } } return controller, nil }
func (container *Container) buildEndpointInfo(n libnetwork.Network, ep libnetwork.Endpoint, networkSettings *network.Settings) (*network.Settings, error) { if ep == nil { return nil, derr.ErrorCodeEmptyEndpoint } if networkSettings == nil { return nil, derr.ErrorCodeEmptyNetwork } epInfo := ep.Info() if epInfo == nil { // It is not an error to get an empty endpoint info return networkSettings, nil } if _, ok := networkSettings.Networks[n.Name()]; !ok { networkSettings.Networks[n.Name()] = new(network.EndpointSettings) } networkSettings.Networks[n.Name()].EndpointID = ep.ID() iface := epInfo.Iface() if iface == nil { return networkSettings, nil } if iface.MacAddress() != nil { networkSettings.Networks[n.Name()].MacAddress = iface.MacAddress().String() } if iface.Address() != nil { ones, _ := iface.Address().Mask.Size() networkSettings.Networks[n.Name()].IPAddress = iface.Address().IP.String() networkSettings.Networks[n.Name()].IPPrefixLen = ones } if iface.AddressIPv6() != nil && iface.AddressIPv6().IP.To16() != nil { onesv6, _ := iface.AddressIPv6().Mask.Size() networkSettings.Networks[n.Name()].GlobalIPv6Address = iface.AddressIPv6().IP.String() networkSettings.Networks[n.Name()].GlobalIPv6PrefixLen = onesv6 } return networkSettings, nil }
func (daemon *Daemon) buildSandboxOptions(container *Container, n libnetwork.Network) ([]libnetwork.SandboxOption, error) { var ( sboxOptions []libnetwork.SandboxOption err error dns []string dnsSearch []string dnsOptions []string ) sboxOptions = append(sboxOptions, libnetwork.OptionHostname(container.Config.Hostname), libnetwork.OptionDomainname(container.Config.Domainname)) if container.hostConfig.NetworkMode.IsHost() { sboxOptions = append(sboxOptions, libnetwork.OptionUseDefaultSandbox()) sboxOptions = append(sboxOptions, libnetwork.OptionOriginHostsPath("/etc/hosts")) sboxOptions = append(sboxOptions, libnetwork.OptionOriginResolvConfPath("/etc/resolv.conf")) } else if daemon.execDriver.SupportsHooks() { // OptionUseExternalKey is mandatory for userns support. // But optional for non-userns support sboxOptions = append(sboxOptions, libnetwork.OptionUseExternalKey()) } container.HostsPath, err = container.getRootResourcePath("hosts") if err != nil { return nil, err } sboxOptions = append(sboxOptions, libnetwork.OptionHostsPath(container.HostsPath)) container.ResolvConfPath, err = container.getRootResourcePath("resolv.conf") if err != nil { return nil, err } sboxOptions = append(sboxOptions, libnetwork.OptionResolvConfPath(container.ResolvConfPath)) if len(container.hostConfig.DNS) > 0 { dns = container.hostConfig.DNS } else if len(daemon.configStore.DNS) > 0 { dns = daemon.configStore.DNS } for _, d := range dns { sboxOptions = append(sboxOptions, libnetwork.OptionDNS(d)) } if len(container.hostConfig.DNSSearch) > 0 { dnsSearch = container.hostConfig.DNSSearch } else if len(daemon.configStore.DNSSearch) > 0 { dnsSearch = daemon.configStore.DNSSearch } for _, ds := range dnsSearch { sboxOptions = append(sboxOptions, libnetwork.OptionDNSSearch(ds)) } if len(container.hostConfig.DNSOptions) > 0 { dnsOptions = container.hostConfig.DNSOptions } else if len(daemon.configStore.DNSOptions) > 0 { dnsOptions = daemon.configStore.DNSOptions } for _, ds := range dnsOptions { sboxOptions = append(sboxOptions, libnetwork.OptionDNSOptions(ds)) } if container.NetworkSettings.SecondaryIPAddresses != nil { name := container.Config.Hostname if container.Config.Domainname != "" { name = name + "." + container.Config.Domainname } for _, a := range container.NetworkSettings.SecondaryIPAddresses { sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(name, a.Addr)) } } for _, extraHost := range container.hostConfig.ExtraHosts { // allow IPv6 addresses in extra hosts; only split on first ":" parts := strings.SplitN(extraHost, ":", 2) sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(parts[0], parts[1])) } // Link feature is supported only for the default bridge network. // return if this call to build join options is not for default bridge network if n.Name() != "bridge" { return sboxOptions, nil } ep, _ := container.getEndpointInNetwork(n) if ep == nil { return sboxOptions, nil } var childEndpoints, parentEndpoints []string children, err := daemon.children(container.Name) if err != nil { return nil, err } for linkAlias, child := range children { if !isLinkable(child) { return nil, fmt.Errorf("Cannot link to %s, as it does not belong to the default network", child.Name) } _, alias := path.Split(linkAlias) // allow access to the linked container via the alias, real name, and container hostname aliasList := alias + " " + child.Config.Hostname // only add the name if alias isn't equal to the name if alias != child.Name[1:] { aliasList = aliasList + " " + child.Name[1:] } sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(aliasList, child.NetworkSettings.Networks["bridge"].IPAddress)) cEndpoint, _ := child.getEndpointInNetwork(n) if cEndpoint != nil && cEndpoint.ID() != "" { childEndpoints = append(childEndpoints, cEndpoint.ID()) } } bridgeSettings := container.NetworkSettings.Networks["bridge"] refs := daemon.containerGraph().RefPaths(container.ID) for _, ref := range refs { if ref.ParentID == "0" { continue } c, err := daemon.Get(ref.ParentID) if err != nil { logrus.Error(err) } if c != nil && !daemon.configStore.DisableBridge && container.hostConfig.NetworkMode.IsPrivate() { logrus.Debugf("Update /etc/hosts of %s for alias %s with ip %s", c.ID, ref.Name, bridgeSettings.IPAddress) sboxOptions = append(sboxOptions, libnetwork.OptionParentUpdate(c.ID, ref.Name, bridgeSettings.IPAddress)) if ep.ID() != "" { parentEndpoints = append(parentEndpoints, ep.ID()) } } } linkOptions := options.Generic{ netlabel.GenericData: options.Generic{ "ParentEndpoints": parentEndpoints, "ChildEndpoints": childEndpoints, }, } sboxOptions = append(sboxOptions, libnetwork.OptionGeneric(linkOptions)) return sboxOptions, nil }
func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkController, error) { netOptions, err := daemon.networkOptions(config) if err != nil { return nil, err } controller, err := libnetwork.New(netOptions...) if err != nil { return nil, fmt.Errorf("error obtaining controller instance: %v", err) } hnsresponse, err := hcsshim.HNSListNetworkRequest("GET", "", "") if err != nil { return nil, err } // Remove networks not present in HNS for _, v := range controller.Networks() { options := v.Info().DriverOptions() hnsid := options[winlibnetwork.HNSID] found := false for _, v := range hnsresponse { if v.Id == hnsid { found = true break } } if !found { err = v.Delete() if err != nil { return nil, err } } } _, err = controller.NewNetwork("null", "none", libnetwork.NetworkOptionPersist(false)) if err != nil { return nil, err } // discover and add HNS networks to windows // network that exist are removed and added again for _, v := range hnsresponse { var n libnetwork.Network s := func(current libnetwork.Network) bool { options := current.Info().DriverOptions() if options[winlibnetwork.HNSID] == v.Id { n = current return true } return false } controller.WalkNetworks(s) if n != nil { v.Name = n.Name() n.Delete() } netOption := map[string]string{ winlibnetwork.NetworkName: v.Name, winlibnetwork.HNSID: v.Id, } v4Conf := []*libnetwork.IpamConf{} for _, subnet := range v.Subnets { ipamV4Conf := libnetwork.IpamConf{} ipamV4Conf.PreferredPool = subnet.AddressPrefix ipamV4Conf.Gateway = subnet.GatewayAddress v4Conf = append(v4Conf, &ipamV4Conf) } name := v.Name // There is only one nat network supported in windows. // If it exists with a different name add it as the default name if runconfig.DefaultDaemonNetworkMode() == containertypes.NetworkMode(strings.ToLower(v.Type)) { name = runconfig.DefaultDaemonNetworkMode().NetworkName() } v6Conf := []*libnetwork.IpamConf{} _, err := controller.NewNetwork(strings.ToLower(v.Type), name, libnetwork.NetworkOptionGeneric(options.Generic{ netlabel.GenericData: netOption, }), libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf, nil), ) if err != nil { logrus.Errorf("Error occurred when creating network %v", err) } } if !config.DisableBridge { // Initialize default driver "bridge" if err := initBridgeDriver(controller, config); err != nil { return nil, err } } return controller, nil }
func (container *Container) buildCreateEndpointOptions(n libnetwork.Network) ([]libnetwork.EndpointOption, error) { var ( portSpecs = make(nat.PortSet) bindings = make(nat.PortMap) pbList []types.PortBinding exposeList []types.TransportPort createOptions []libnetwork.EndpointOption ) if n.Name() == "bridge" || container.NetworkSettings.IsAnonymousEndpoint { createOptions = append(createOptions, libnetwork.CreateOptionAnonymous()) } // Other configs are applicable only for the endpoint in the network // to which container was connected to on docker run. if n.Name() != container.hostConfig.NetworkMode.NetworkName() && !(n.Name() == "bridge" && container.hostConfig.NetworkMode.IsDefault()) { return createOptions, nil } if container.Config.ExposedPorts != nil { portSpecs = container.Config.ExposedPorts } if container.hostConfig.PortBindings != nil { for p, b := range container.hostConfig.PortBindings { bindings[p] = []nat.PortBinding{} for _, bb := range b { bindings[p] = append(bindings[p], nat.PortBinding{ HostIP: bb.HostIP, HostPort: bb.HostPort, }) } } } ports := make([]nat.Port, len(portSpecs)) var i int for p := range portSpecs { ports[i] = p i++ } nat.SortPortMap(ports, bindings) for _, port := range ports { expose := types.TransportPort{} expose.Proto = types.ParseProtocol(port.Proto()) expose.Port = uint16(port.Int()) exposeList = append(exposeList, expose) pb := types.PortBinding{Port: expose.Port, Proto: expose.Proto} binding := bindings[port] for i := 0; i < len(binding); i++ { pbCopy := pb.GetCopy() newP, err := nat.NewPort(nat.SplitProtoPort(binding[i].HostPort)) var portStart, portEnd int if err == nil { portStart, portEnd, err = newP.Range() } if err != nil { return nil, derr.ErrorCodeHostPort.WithArgs(binding[i].HostPort, err) } pbCopy.HostPort = uint16(portStart) pbCopy.HostPortEnd = uint16(portEnd) pbCopy.HostIP = net.ParseIP(binding[i].HostIP) pbList = append(pbList, pbCopy) } if container.hostConfig.PublishAllPorts && len(binding) == 0 { pbList = append(pbList, pb) } } createOptions = append(createOptions, libnetwork.CreateOptionPortMapping(pbList), libnetwork.CreateOptionExposedPorts(exposeList)) if container.Config.MacAddress != "" { mac, err := net.ParseMAC(container.Config.MacAddress) if err != nil { return nil, err } genericOption := options.Generic{ netlabel.MacAddress: mac, } createOptions = append(createOptions, libnetwork.EndpointOptionGeneric(genericOption)) } return createOptions, nil }
func (daemon *Daemon) buildSandboxOptions(container *container.Container, n libnetwork.Network) ([]libnetwork.SandboxOption, error) { var ( sboxOptions []libnetwork.SandboxOption err error dns []string dnsSearch []string dnsOptions []string bindings = make(nat.PortMap) pbList []types.PortBinding exposeList []types.TransportPort ) defaultNetName := runconfig.DefaultDaemonNetworkMode().NetworkName() sboxOptions = append(sboxOptions, libnetwork.OptionHostname(container.Config.Hostname), libnetwork.OptionDomainname(container.Config.Domainname)) if container.HostConfig.NetworkMode.IsHost() { sboxOptions = append(sboxOptions, libnetwork.OptionUseDefaultSandbox()) sboxOptions = append(sboxOptions, libnetwork.OptionOriginHostsPath("/etc/hosts")) sboxOptions = append(sboxOptions, libnetwork.OptionOriginResolvConfPath("/etc/resolv.conf")) } else if daemon.execDriver.SupportsHooks() { // OptionUseExternalKey is mandatory for userns support. // But optional for non-userns support sboxOptions = append(sboxOptions, libnetwork.OptionUseExternalKey()) } container.HostsPath, err = container.GetRootResourcePath("hosts") if err != nil { return nil, err } sboxOptions = append(sboxOptions, libnetwork.OptionHostsPath(container.HostsPath)) container.ResolvConfPath, err = container.GetRootResourcePath("resolv.conf") if err != nil { return nil, err } sboxOptions = append(sboxOptions, libnetwork.OptionResolvConfPath(container.ResolvConfPath)) if len(container.HostConfig.DNS) > 0 { dns = container.HostConfig.DNS } else if len(daemon.configStore.DNS) > 0 { dns = daemon.configStore.DNS } for _, d := range dns { sboxOptions = append(sboxOptions, libnetwork.OptionDNS(d)) } if len(container.HostConfig.DNSSearch) > 0 { dnsSearch = container.HostConfig.DNSSearch } else if len(daemon.configStore.DNSSearch) > 0 { dnsSearch = daemon.configStore.DNSSearch } for _, ds := range dnsSearch { sboxOptions = append(sboxOptions, libnetwork.OptionDNSSearch(ds)) } if len(container.HostConfig.DNSOptions) > 0 { dnsOptions = container.HostConfig.DNSOptions } else if len(daemon.configStore.DNSOptions) > 0 { dnsOptions = daemon.configStore.DNSOptions } for _, ds := range dnsOptions { sboxOptions = append(sboxOptions, libnetwork.OptionDNSOptions(ds)) } if container.NetworkSettings.SecondaryIPAddresses != nil { name := container.Config.Hostname if container.Config.Domainname != "" { name = name + "." + container.Config.Domainname } for _, a := range container.NetworkSettings.SecondaryIPAddresses { sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(name, a.Addr)) } } for _, extraHost := range container.HostConfig.ExtraHosts { // allow IPv6 addresses in extra hosts; only split on first ":" parts := strings.SplitN(extraHost, ":", 2) sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(parts[0], parts[1])) } if container.HostConfig.PortBindings != nil { for p, b := range container.HostConfig.PortBindings { bindings[p] = []nat.PortBinding{} for _, bb := range b { bindings[p] = append(bindings[p], nat.PortBinding{ HostIP: bb.HostIP, HostPort: bb.HostPort, }) } } } portSpecs := container.Config.ExposedPorts ports := make([]nat.Port, len(portSpecs)) var i int for p := range portSpecs { ports[i] = p i++ } nat.SortPortMap(ports, bindings) for _, port := range ports { expose := types.TransportPort{} expose.Proto = types.ParseProtocol(port.Proto()) expose.Port = uint16(port.Int()) exposeList = append(exposeList, expose) pb := types.PortBinding{Port: expose.Port, Proto: expose.Proto} binding := bindings[port] for i := 0; i < len(binding); i++ { pbCopy := pb.GetCopy() newP, err := nat.NewPort(nat.SplitProtoPort(binding[i].HostPort)) var portStart, portEnd int if err == nil { portStart, portEnd, err = newP.Range() } if err != nil { return nil, fmt.Errorf("Error parsing HostPort value(%s):%v", binding[i].HostPort, err) } pbCopy.HostPort = uint16(portStart) pbCopy.HostPortEnd = uint16(portEnd) pbCopy.HostIP = net.ParseIP(binding[i].HostIP) pbList = append(pbList, pbCopy) } if container.HostConfig.PublishAllPorts && len(binding) == 0 { pbList = append(pbList, pb) } } sboxOptions = append(sboxOptions, libnetwork.OptionPortMapping(pbList), libnetwork.OptionExposedPorts(exposeList)) // Link feature is supported only for the default bridge network. // return if this call to build join options is not for default bridge network if n.Name() != defaultNetName { return sboxOptions, nil } ep, _ := container.GetEndpointInNetwork(n) if ep == nil { return sboxOptions, nil } var childEndpoints, parentEndpoints []string children := daemon.children(container) for linkAlias, child := range children { if !isLinkable(child) { return nil, fmt.Errorf("Cannot link to %s, as it does not belong to the default network", child.Name) } _, alias := path.Split(linkAlias) // allow access to the linked container via the alias, real name, and container hostname aliasList := alias + " " + child.Config.Hostname // only add the name if alias isn't equal to the name if alias != child.Name[1:] { aliasList = aliasList + " " + child.Name[1:] } sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(aliasList, child.NetworkSettings.Networks[defaultNetName].IPAddress)) cEndpoint, _ := child.GetEndpointInNetwork(n) if cEndpoint != nil && cEndpoint.ID() != "" { childEndpoints = append(childEndpoints, cEndpoint.ID()) } } bridgeSettings := container.NetworkSettings.Networks[defaultNetName] for alias, parent := range daemon.parents(container) { if daemon.configStore.DisableBridge || !container.HostConfig.NetworkMode.IsPrivate() { continue } _, alias = path.Split(alias) logrus.Debugf("Update /etc/hosts of %s for alias %s with ip %s", parent.ID, alias, bridgeSettings.IPAddress) sboxOptions = append(sboxOptions, libnetwork.OptionParentUpdate( parent.ID, alias, bridgeSettings.IPAddress, )) if ep.ID() != "" { parentEndpoints = append(parentEndpoints, ep.ID()) } } linkOptions := options.Generic{ netlabel.GenericData: options.Generic{ "ParentEndpoints": parentEndpoints, "ChildEndpoints": childEndpoints, }, } sboxOptions = append(sboxOptions, libnetwork.OptionGeneric(linkOptions)) return sboxOptions, nil }