github.com/noxiouz/docker@v0.7.3-0.20160629055221-3d231c78e8c5/daemon/container_operations.go (about) 1 package daemon 2 3 import ( 4 "errors" 5 "fmt" 6 "net" 7 "os" 8 "path" 9 "strings" 10 11 "github.com/Sirupsen/logrus" 12 "github.com/docker/docker/container" 13 "github.com/docker/docker/daemon/network" 14 derr "github.com/docker/docker/errors" 15 "github.com/docker/docker/pkg/stringid" 16 "github.com/docker/docker/runconfig" 17 containertypes "github.com/docker/engine-api/types/container" 18 networktypes "github.com/docker/engine-api/types/network" 19 "github.com/docker/go-connections/nat" 20 "github.com/docker/libnetwork" 21 "github.com/docker/libnetwork/netlabel" 22 "github.com/docker/libnetwork/options" 23 "github.com/docker/libnetwork/types" 24 ) 25 26 var ( 27 // ErrRootFSReadOnly is returned when a container 28 // rootfs is marked readonly. 29 ErrRootFSReadOnly = errors.New("container rootfs is marked read-only") 30 getPortMapInfo = container.GetSandboxPortMapInfo 31 ) 32 33 func (daemon *Daemon) buildSandboxOptions(container *container.Container) ([]libnetwork.SandboxOption, error) { 34 var ( 35 sboxOptions []libnetwork.SandboxOption 36 err error 37 dns []string 38 dnsSearch []string 39 dnsOptions []string 40 bindings = make(nat.PortMap) 41 pbList []types.PortBinding 42 exposeList []types.TransportPort 43 ) 44 45 defaultNetName := runconfig.DefaultDaemonNetworkMode().NetworkName() 46 sboxOptions = append(sboxOptions, libnetwork.OptionHostname(container.Config.Hostname), 47 libnetwork.OptionDomainname(container.Config.Domainname)) 48 49 if container.HostConfig.NetworkMode.IsHost() { 50 sboxOptions = append(sboxOptions, libnetwork.OptionUseDefaultSandbox()) 51 if len(container.HostConfig.ExtraHosts) == 0 { 52 sboxOptions = append(sboxOptions, libnetwork.OptionOriginHostsPath("/etc/hosts")) 53 } 54 if len(container.HostConfig.DNS) == 0 && len(daemon.configStore.DNS) == 0 && 55 len(container.HostConfig.DNSSearch) == 0 && len(daemon.configStore.DNSSearch) == 0 && 56 len(container.HostConfig.DNSOptions) == 0 && len(daemon.configStore.DNSOptions) == 0 { 57 sboxOptions = append(sboxOptions, libnetwork.OptionOriginResolvConfPath("/etc/resolv.conf")) 58 } 59 } else { 60 // OptionUseExternalKey is mandatory for userns support. 61 // But optional for non-userns support 62 sboxOptions = append(sboxOptions, libnetwork.OptionUseExternalKey()) 63 } 64 65 container.HostsPath, err = container.GetRootResourcePath("hosts") 66 if err != nil { 67 return nil, err 68 } 69 sboxOptions = append(sboxOptions, libnetwork.OptionHostsPath(container.HostsPath)) 70 71 container.ResolvConfPath, err = container.GetRootResourcePath("resolv.conf") 72 if err != nil { 73 return nil, err 74 } 75 sboxOptions = append(sboxOptions, libnetwork.OptionResolvConfPath(container.ResolvConfPath)) 76 77 if len(container.HostConfig.DNS) > 0 { 78 dns = container.HostConfig.DNS 79 } else if len(daemon.configStore.DNS) > 0 { 80 dns = daemon.configStore.DNS 81 } 82 83 for _, d := range dns { 84 sboxOptions = append(sboxOptions, libnetwork.OptionDNS(d)) 85 } 86 87 if len(container.HostConfig.DNSSearch) > 0 { 88 dnsSearch = container.HostConfig.DNSSearch 89 } else if len(daemon.configStore.DNSSearch) > 0 { 90 dnsSearch = daemon.configStore.DNSSearch 91 } 92 93 for _, ds := range dnsSearch { 94 sboxOptions = append(sboxOptions, libnetwork.OptionDNSSearch(ds)) 95 } 96 97 if len(container.HostConfig.DNSOptions) > 0 { 98 dnsOptions = container.HostConfig.DNSOptions 99 } else if len(daemon.configStore.DNSOptions) > 0 { 100 dnsOptions = daemon.configStore.DNSOptions 101 } 102 103 for _, ds := range dnsOptions { 104 sboxOptions = append(sboxOptions, libnetwork.OptionDNSOptions(ds)) 105 } 106 107 if container.NetworkSettings.SecondaryIPAddresses != nil { 108 name := container.Config.Hostname 109 if container.Config.Domainname != "" { 110 name = name + "." + container.Config.Domainname 111 } 112 113 for _, a := range container.NetworkSettings.SecondaryIPAddresses { 114 sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(name, a.Addr)) 115 } 116 } 117 118 for _, extraHost := range container.HostConfig.ExtraHosts { 119 // allow IPv6 addresses in extra hosts; only split on first ":" 120 parts := strings.SplitN(extraHost, ":", 2) 121 sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(parts[0], parts[1])) 122 } 123 124 if container.HostConfig.PortBindings != nil { 125 for p, b := range container.HostConfig.PortBindings { 126 bindings[p] = []nat.PortBinding{} 127 for _, bb := range b { 128 bindings[p] = append(bindings[p], nat.PortBinding{ 129 HostIP: bb.HostIP, 130 HostPort: bb.HostPort, 131 }) 132 } 133 } 134 } 135 136 portSpecs := container.Config.ExposedPorts 137 ports := make([]nat.Port, len(portSpecs)) 138 var i int 139 for p := range portSpecs { 140 ports[i] = p 141 i++ 142 } 143 nat.SortPortMap(ports, bindings) 144 for _, port := range ports { 145 expose := types.TransportPort{} 146 expose.Proto = types.ParseProtocol(port.Proto()) 147 expose.Port = uint16(port.Int()) 148 exposeList = append(exposeList, expose) 149 150 pb := types.PortBinding{Port: expose.Port, Proto: expose.Proto} 151 binding := bindings[port] 152 for i := 0; i < len(binding); i++ { 153 pbCopy := pb.GetCopy() 154 newP, err := nat.NewPort(nat.SplitProtoPort(binding[i].HostPort)) 155 var portStart, portEnd int 156 if err == nil { 157 portStart, portEnd, err = newP.Range() 158 } 159 if err != nil { 160 return nil, fmt.Errorf("Error parsing HostPort value(%s):%v", binding[i].HostPort, err) 161 } 162 pbCopy.HostPort = uint16(portStart) 163 pbCopy.HostPortEnd = uint16(portEnd) 164 pbCopy.HostIP = net.ParseIP(binding[i].HostIP) 165 pbList = append(pbList, pbCopy) 166 } 167 168 if container.HostConfig.PublishAllPorts && len(binding) == 0 { 169 pbList = append(pbList, pb) 170 } 171 } 172 173 sboxOptions = append(sboxOptions, 174 libnetwork.OptionPortMapping(pbList), 175 libnetwork.OptionExposedPorts(exposeList)) 176 177 // Legacy Link feature is supported only for the default bridge network. 178 // return if this call to build join options is not for default bridge network 179 // Legacy Link is only supported by docker run --link 180 if _, ok := container.NetworkSettings.Networks[defaultNetName]; !container.HostConfig.NetworkMode.IsDefault() || !ok { 181 return sboxOptions, nil 182 } 183 184 if container.NetworkSettings.Networks[defaultNetName].EndpointID == "" { 185 return sboxOptions, nil 186 } 187 188 var ( 189 childEndpoints, parentEndpoints []string 190 cEndpointID string 191 ) 192 193 children := daemon.children(container) 194 for linkAlias, child := range children { 195 if !isLinkable(child) { 196 return nil, fmt.Errorf("Cannot link to %s, as it does not belong to the default network", child.Name) 197 } 198 _, alias := path.Split(linkAlias) 199 // allow access to the linked container via the alias, real name, and container hostname 200 aliasList := alias + " " + child.Config.Hostname 201 // only add the name if alias isn't equal to the name 202 if alias != child.Name[1:] { 203 aliasList = aliasList + " " + child.Name[1:] 204 } 205 sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(aliasList, child.NetworkSettings.Networks[defaultNetName].IPAddress)) 206 cEndpointID = child.NetworkSettings.Networks[defaultNetName].EndpointID 207 if cEndpointID != "" { 208 childEndpoints = append(childEndpoints, cEndpointID) 209 } 210 } 211 212 bridgeSettings := container.NetworkSettings.Networks[defaultNetName] 213 for alias, parent := range daemon.parents(container) { 214 if daemon.configStore.DisableBridge || !container.HostConfig.NetworkMode.IsPrivate() { 215 continue 216 } 217 218 _, alias = path.Split(alias) 219 logrus.Debugf("Update /etc/hosts of %s for alias %s with ip %s", parent.ID, alias, bridgeSettings.IPAddress) 220 sboxOptions = append(sboxOptions, libnetwork.OptionParentUpdate( 221 parent.ID, 222 alias, 223 bridgeSettings.IPAddress, 224 )) 225 if cEndpointID != "" { 226 parentEndpoints = append(parentEndpoints, cEndpointID) 227 } 228 } 229 230 linkOptions := options.Generic{ 231 netlabel.GenericData: options.Generic{ 232 "ParentEndpoints": parentEndpoints, 233 "ChildEndpoints": childEndpoints, 234 }, 235 } 236 237 sboxOptions = append(sboxOptions, libnetwork.OptionGeneric(linkOptions)) 238 return sboxOptions, nil 239 } 240 241 func (daemon *Daemon) updateNetworkSettings(container *container.Container, n libnetwork.Network) error { 242 if container.NetworkSettings == nil { 243 container.NetworkSettings = &network.Settings{Networks: make(map[string]*networktypes.EndpointSettings)} 244 } 245 246 if !container.HostConfig.NetworkMode.IsHost() && containertypes.NetworkMode(n.Type()).IsHost() { 247 return runconfig.ErrConflictHostNetwork 248 } 249 250 for s := range container.NetworkSettings.Networks { 251 sn, err := daemon.FindNetwork(s) 252 if err != nil { 253 continue 254 } 255 256 if sn.Name() == n.Name() { 257 // Avoid duplicate config 258 return nil 259 } 260 if !containertypes.NetworkMode(sn.Type()).IsPrivate() || 261 !containertypes.NetworkMode(n.Type()).IsPrivate() { 262 return runconfig.ErrConflictSharedNetwork 263 } 264 if containertypes.NetworkMode(sn.Name()).IsNone() || 265 containertypes.NetworkMode(n.Name()).IsNone() { 266 return runconfig.ErrConflictNoNetwork 267 } 268 } 269 270 if _, ok := container.NetworkSettings.Networks[n.Name()]; !ok { 271 container.NetworkSettings.Networks[n.Name()] = new(networktypes.EndpointSettings) 272 } 273 274 return nil 275 } 276 277 func (daemon *Daemon) updateEndpointNetworkSettings(container *container.Container, n libnetwork.Network, ep libnetwork.Endpoint) error { 278 if err := container.BuildEndpointInfo(n, ep); err != nil { 279 return err 280 } 281 282 if container.HostConfig.NetworkMode == runconfig.DefaultDaemonNetworkMode() { 283 container.NetworkSettings.Bridge = daemon.configStore.bridgeConfig.Iface 284 } 285 286 return nil 287 } 288 289 // UpdateNetwork is used to update the container's network (e.g. when linked containers 290 // get removed/unlinked). 291 func (daemon *Daemon) updateNetwork(container *container.Container) error { 292 ctrl := daemon.netController 293 sid := container.NetworkSettings.SandboxID 294 295 sb, err := ctrl.SandboxByID(sid) 296 if err != nil { 297 return fmt.Errorf("error locating sandbox id %s: %v", sid, err) 298 } 299 300 // Find if container is connected to the default bridge network 301 var n libnetwork.Network 302 for name := range container.NetworkSettings.Networks { 303 sn, err := daemon.FindNetwork(name) 304 if err != nil { 305 continue 306 } 307 if sn.Name() == runconfig.DefaultDaemonNetworkMode().NetworkName() { 308 n = sn 309 break 310 } 311 } 312 313 if n == nil { 314 // Not connected to the default bridge network; Nothing to do 315 return nil 316 } 317 318 options, err := daemon.buildSandboxOptions(container) 319 if err != nil { 320 return fmt.Errorf("Update network failed: %v", err) 321 } 322 323 if err := sb.Refresh(options...); err != nil { 324 return fmt.Errorf("Update network failed: Failure in refresh sandbox %s: %v", sid, err) 325 } 326 327 return nil 328 } 329 330 func errClusterNetworkOnRun(n string) error { 331 return fmt.Errorf("swarm-scoped network (%s) is not compatible with `docker create` or `docker run`. This network can be only used docker service", n) 332 } 333 334 // updateContainerNetworkSettings update the network settings 335 func (daemon *Daemon) updateContainerNetworkSettings(container *container.Container, endpointsConfig map[string]*networktypes.EndpointSettings) error { 336 var ( 337 n libnetwork.Network 338 err error 339 ) 340 341 mode := container.HostConfig.NetworkMode 342 if container.Config.NetworkDisabled || mode.IsContainer() { 343 return nil 344 } 345 346 networkName := mode.NetworkName() 347 if mode.IsDefault() { 348 networkName = daemon.netController.Config().Daemon.DefaultNetwork 349 } 350 if mode.IsUserDefined() { 351 n, err = daemon.FindNetwork(networkName) 352 if err != nil { 353 return err 354 } 355 if !container.Managed && n.Info().Dynamic() { 356 return errClusterNetworkOnRun(networkName) 357 } 358 networkName = n.Name() 359 } 360 if container.NetworkSettings == nil { 361 container.NetworkSettings = &network.Settings{} 362 } 363 if len(endpointsConfig) > 0 { 364 container.NetworkSettings.Networks = endpointsConfig 365 } 366 if container.NetworkSettings.Networks == nil { 367 container.NetworkSettings.Networks = make(map[string]*networktypes.EndpointSettings) 368 container.NetworkSettings.Networks[networkName] = new(networktypes.EndpointSettings) 369 } 370 if !mode.IsUserDefined() { 371 return nil 372 } 373 // Make sure to internally store the per network endpoint config by network name 374 if _, ok := container.NetworkSettings.Networks[networkName]; ok { 375 return nil 376 } 377 if nwConfig, ok := container.NetworkSettings.Networks[n.ID()]; ok { 378 container.NetworkSettings.Networks[networkName] = nwConfig 379 delete(container.NetworkSettings.Networks, n.ID()) 380 return nil 381 } 382 383 return nil 384 } 385 386 func (daemon *Daemon) allocateNetwork(container *container.Container) error { 387 controller := daemon.netController 388 389 if daemon.netController == nil { 390 return nil 391 } 392 393 // Cleanup any stale sandbox left over due to ungraceful daemon shutdown 394 if err := controller.SandboxDestroy(container.ID); err != nil { 395 logrus.Errorf("failed to cleanup up stale network sandbox for container %s", container.ID) 396 } 397 398 updateSettings := false 399 if len(container.NetworkSettings.Networks) == 0 { 400 if container.Config.NetworkDisabled || container.HostConfig.NetworkMode.IsContainer() { 401 return nil 402 } 403 404 err := daemon.updateContainerNetworkSettings(container, nil) 405 if err != nil { 406 return err 407 } 408 updateSettings = true 409 } 410 411 // always connect default network first since only default 412 // network mode support link and we need do some setting 413 // on sandbox initialize for link, but the sandbox only be initialized 414 // on first network connecting. 415 defaultNetName := runconfig.DefaultDaemonNetworkMode().NetworkName() 416 if nConf, ok := container.NetworkSettings.Networks[defaultNetName]; ok { 417 if err := daemon.connectToNetwork(container, defaultNetName, nConf, updateSettings); err != nil { 418 return err 419 } 420 421 } 422 for n, nConf := range container.NetworkSettings.Networks { 423 if n == defaultNetName { 424 continue 425 } 426 if err := daemon.connectToNetwork(container, n, nConf, updateSettings); err != nil { 427 return err 428 } 429 } 430 431 return container.WriteHostConfig() 432 } 433 434 func (daemon *Daemon) getNetworkSandbox(container *container.Container) libnetwork.Sandbox { 435 var sb libnetwork.Sandbox 436 daemon.netController.WalkSandboxes(func(s libnetwork.Sandbox) bool { 437 if s.ContainerID() == container.ID { 438 sb = s 439 return true 440 } 441 return false 442 }) 443 return sb 444 } 445 446 // hasUserDefinedIPAddress returns whether the passed endpoint configuration contains IP address configuration 447 func hasUserDefinedIPAddress(epConfig *networktypes.EndpointSettings) bool { 448 return epConfig != nil && epConfig.IPAMConfig != nil && (len(epConfig.IPAMConfig.IPv4Address) > 0 || len(epConfig.IPAMConfig.IPv6Address) > 0) 449 } 450 451 // User specified ip address is acceptable only for networks with user specified subnets. 452 func validateNetworkingConfig(n libnetwork.Network, epConfig *networktypes.EndpointSettings) error { 453 if n == nil || epConfig == nil { 454 return nil 455 } 456 if !hasUserDefinedIPAddress(epConfig) { 457 return nil 458 } 459 _, _, nwIPv4Configs, nwIPv6Configs := n.Info().IpamConfig() 460 for _, s := range []struct { 461 ipConfigured bool 462 subnetConfigs []*libnetwork.IpamConf 463 }{ 464 { 465 ipConfigured: len(epConfig.IPAMConfig.IPv4Address) > 0, 466 subnetConfigs: nwIPv4Configs, 467 }, 468 { 469 ipConfigured: len(epConfig.IPAMConfig.IPv6Address) > 0, 470 subnetConfigs: nwIPv6Configs, 471 }, 472 } { 473 if s.ipConfigured { 474 foundSubnet := false 475 for _, cfg := range s.subnetConfigs { 476 if len(cfg.PreferredPool) > 0 { 477 foundSubnet = true 478 break 479 } 480 } 481 if !foundSubnet { 482 return runconfig.ErrUnsupportedNetworkNoSubnetAndIP 483 } 484 } 485 } 486 487 return nil 488 } 489 490 // cleanOperationalData resets the operational data from the passed endpoint settings 491 func cleanOperationalData(es *networktypes.EndpointSettings) { 492 es.EndpointID = "" 493 es.Gateway = "" 494 es.IPAddress = "" 495 es.IPPrefixLen = 0 496 es.IPv6Gateway = "" 497 es.GlobalIPv6Address = "" 498 es.GlobalIPv6PrefixLen = 0 499 es.MacAddress = "" 500 } 501 502 func (daemon *Daemon) updateNetworkConfig(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings, updateSettings bool) (libnetwork.Network, error) { 503 if container.HostConfig.NetworkMode.IsContainer() { 504 return nil, runconfig.ErrConflictSharedNetwork 505 } 506 507 if containertypes.NetworkMode(idOrName).IsBridge() && 508 daemon.configStore.DisableBridge { 509 container.Config.NetworkDisabled = true 510 return nil, nil 511 } 512 513 if !containertypes.NetworkMode(idOrName).IsUserDefined() { 514 if hasUserDefinedIPAddress(endpointConfig) { 515 return nil, runconfig.ErrUnsupportedNetworkAndIP 516 } 517 if endpointConfig != nil && len(endpointConfig.Aliases) > 0 { 518 return nil, runconfig.ErrUnsupportedNetworkAndAlias 519 } 520 } else { 521 addShortID := true 522 shortID := stringid.TruncateID(container.ID) 523 for _, alias := range endpointConfig.Aliases { 524 if alias == shortID { 525 addShortID = false 526 break 527 } 528 } 529 if addShortID { 530 endpointConfig.Aliases = append(endpointConfig.Aliases, shortID) 531 } 532 } 533 534 n, err := daemon.FindNetwork(idOrName) 535 if err != nil { 536 return nil, err 537 } 538 539 if err := validateNetworkingConfig(n, endpointConfig); err != nil { 540 return nil, err 541 } 542 543 if updateSettings { 544 if err := daemon.updateNetworkSettings(container, n); err != nil { 545 return nil, err 546 } 547 } 548 return n, nil 549 } 550 551 func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings, updateSettings bool) (err error) { 552 if endpointConfig == nil { 553 endpointConfig = &networktypes.EndpointSettings{} 554 } 555 n, err := daemon.updateNetworkConfig(container, idOrName, endpointConfig, updateSettings) 556 if err != nil { 557 return err 558 } 559 if n == nil { 560 return nil 561 } 562 563 controller := daemon.netController 564 565 sb := daemon.getNetworkSandbox(container) 566 createOptions, err := container.BuildCreateEndpointOptions(n, endpointConfig, sb) 567 if err != nil { 568 return err 569 } 570 571 endpointName := strings.TrimPrefix(container.Name, "/") 572 ep, err := n.CreateEndpoint(endpointName, createOptions...) 573 if err != nil { 574 return err 575 } 576 defer func() { 577 if err != nil { 578 if e := ep.Delete(false); e != nil { 579 logrus.Warnf("Could not rollback container connection to network %s", idOrName) 580 } 581 } 582 }() 583 container.NetworkSettings.Networks[n.Name()] = endpointConfig 584 585 if err := daemon.updateEndpointNetworkSettings(container, n, ep); err != nil { 586 return err 587 } 588 589 if sb == nil { 590 options, err := daemon.buildSandboxOptions(container) 591 if err != nil { 592 return err 593 } 594 sb, err = controller.NewSandbox(container.ID, options...) 595 if err != nil { 596 return err 597 } 598 599 container.UpdateSandboxNetworkSettings(sb) 600 } 601 602 joinOptions, err := container.BuildJoinOptions(n) 603 if err != nil { 604 return err 605 } 606 607 if err := ep.Join(sb, joinOptions...); err != nil { 608 return err 609 } 610 611 if err := container.UpdateJoinInfo(n, ep); err != nil { 612 return fmt.Errorf("Updating join info failed: %v", err) 613 } 614 615 container.NetworkSettings.Ports = getPortMapInfo(sb) 616 617 daemon.LogNetworkEventWithAttributes(n, "connect", map[string]string{"container": container.ID}) 618 return nil 619 } 620 621 // ForceEndpointDelete deletes an endpoing from a network forcefully 622 func (daemon *Daemon) ForceEndpointDelete(name string, n libnetwork.Network) error { 623 ep, err := n.EndpointByName(name) 624 if err != nil { 625 return err 626 } 627 return ep.Delete(true) 628 } 629 630 func disconnectFromNetwork(container *container.Container, n libnetwork.Network, force bool) error { 631 var ( 632 ep libnetwork.Endpoint 633 sbox libnetwork.Sandbox 634 ) 635 636 s := func(current libnetwork.Endpoint) bool { 637 epInfo := current.Info() 638 if epInfo == nil { 639 return false 640 } 641 if sb := epInfo.Sandbox(); sb != nil { 642 if sb.ContainerID() == container.ID { 643 ep = current 644 sbox = sb 645 return true 646 } 647 } 648 return false 649 } 650 n.WalkEndpoints(s) 651 652 if ep == nil && force { 653 epName := strings.TrimPrefix(container.Name, "/") 654 ep, err := n.EndpointByName(epName) 655 if err != nil { 656 return err 657 } 658 return ep.Delete(force) 659 } 660 661 if ep == nil { 662 return fmt.Errorf("container %s is not connected to the network", container.ID) 663 } 664 665 if err := ep.Leave(sbox); err != nil { 666 return fmt.Errorf("container %s failed to leave network %s: %v", container.ID, n.Name(), err) 667 } 668 669 container.NetworkSettings.Ports = getPortMapInfo(sbox) 670 671 if err := ep.Delete(false); err != nil { 672 return fmt.Errorf("endpoint delete failed for container %s on network %s: %v", container.ID, n.Name(), err) 673 } 674 675 delete(container.NetworkSettings.Networks, n.Name()) 676 return nil 677 } 678 679 func (daemon *Daemon) initializeNetworking(container *container.Container) error { 680 var err error 681 682 if container.HostConfig.NetworkMode.IsContainer() { 683 // we need to get the hosts files from the container to join 684 nc, err := daemon.getNetworkedContainer(container.ID, container.HostConfig.NetworkMode.ConnectedContainer()) 685 if err != nil { 686 return err 687 } 688 container.HostnamePath = nc.HostnamePath 689 container.HostsPath = nc.HostsPath 690 container.ResolvConfPath = nc.ResolvConfPath 691 container.Config.Hostname = nc.Config.Hostname 692 container.Config.Domainname = nc.Config.Domainname 693 return nil 694 } 695 696 if container.HostConfig.NetworkMode.IsHost() { 697 container.Config.Hostname, err = os.Hostname() 698 if err != nil { 699 return err 700 } 701 } 702 703 if err := daemon.allocateNetwork(container); err != nil { 704 return err 705 } 706 707 return container.BuildHostnameFile() 708 } 709 710 func (daemon *Daemon) getNetworkedContainer(containerID, connectedContainerID string) (*container.Container, error) { 711 nc, err := daemon.GetContainer(connectedContainerID) 712 if err != nil { 713 return nil, err 714 } 715 if containerID == nc.ID { 716 return nil, fmt.Errorf("cannot join own network") 717 } 718 if !nc.IsRunning() { 719 err := fmt.Errorf("cannot join network of a non running container: %s", connectedContainerID) 720 return nil, derr.NewRequestConflictError(err) 721 } 722 if nc.IsRestarting() { 723 return nil, errContainerIsRestarting(connectedContainerID) 724 } 725 return nc, nil 726 } 727 728 func (daemon *Daemon) releaseNetwork(container *container.Container) { 729 if daemon.netController == nil { 730 return 731 } 732 if container.HostConfig.NetworkMode.IsContainer() || container.Config.NetworkDisabled { 733 return 734 } 735 736 sid := container.NetworkSettings.SandboxID 737 settings := container.NetworkSettings.Networks 738 container.NetworkSettings.Ports = nil 739 740 if sid == "" || len(settings) == 0 { 741 return 742 } 743 744 var networks []libnetwork.Network 745 for n, epSettings := range settings { 746 if nw, err := daemon.FindNetwork(n); err == nil { 747 networks = append(networks, nw) 748 } 749 cleanOperationalData(epSettings) 750 } 751 752 sb, err := daemon.netController.SandboxByID(sid) 753 if err != nil { 754 logrus.Warnf("error locating sandbox id %s: %v", sid, err) 755 return 756 } 757 758 if err := sb.Delete(); err != nil { 759 logrus.Errorf("Error deleting sandbox id %s for container %s: %v", sid, container.ID, err) 760 } 761 762 for _, nw := range networks { 763 attributes := map[string]string{ 764 "container": container.ID, 765 } 766 daemon.LogNetworkEventWithAttributes(nw, "disconnect", attributes) 767 } 768 }