// registerLinks writes the links to a file. func (daemon *Daemon) registerLinks(container *container.Container, hostConfig *containertypes.HostConfig) error { if hostConfig == nil || hostConfig.NetworkMode.IsUserDefined() { return nil } for _, l := range hostConfig.Links { name, alias, err := runconfigopts.ParseLink(l) if err != nil { return err } child, err := daemon.GetContainer(name) if err != nil { //An error from daemon.GetContainer() means this name could not be found return fmt.Errorf("Could not get container for %s", name) } for child.HostConfig.NetworkMode.IsContainer() { parts := strings.SplitN(string(child.HostConfig.NetworkMode), ":", 2) child, err = daemon.GetContainer(parts[1]) if err != nil { return fmt.Errorf("Could not get container for %s", parts[1]) } } if child.HostConfig.NetworkMode.IsHost() { return runconfig.ErrConflictHostNetworkAndLinks } if err := daemon.registerLink(container, child, alias); err != nil { return err } } // After we load all the links into the daemon // set them to nil on the hostconfig return container.WriteHostConfig() }
func (daemon *Daemon) allocateNetwork(container *container.Container) error { controller := daemon.netController // Cleanup any stale sandbox left over due to ungraceful daemon shutdown if err := controller.SandboxDestroy(container.ID); err != nil { 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 } err := daemon.updateContainerNetworkSettings(container, nil) if err != nil { return err } updateSettings = true } for n, nConf := range container.NetworkSettings.Networks { if err := daemon.connectToNetwork(container, n, nConf, updateSettings); err != nil { return err } } return container.WriteHostConfig() }
// migrateLegacySqliteLinks migrates sqlite links to use links from HostConfig // when sqlite links were used, hostConfig.Links was set to nil func (daemon *Daemon) migrateLegacySqliteLinks(db *graphdb.Database, container *container.Container) error { // if links is populated (or an empty slice), then this isn't using sqlite links and can be skipped if container.HostConfig == nil || container.HostConfig.Links != nil { return nil } logrus.Debugf("migrating legacy sqlite link info for container: %s", container.ID) fullName := container.Name if fullName[0] != '/' { fullName = "/" + fullName } // don't use a nil slice, this ensures that the check above will skip once the migration has completed links := []string{} children, err := db.Children(fullName, 0) if err != nil { if !strings.Contains(err.Error(), "Cannot find child for") { return err } // else continue... it's ok if we didn't find any children, it'll just be nil and we can continue the migration } for _, child := range children { c, err := daemon.GetContainer(child.Entity.ID()) if err != nil { return err } links = append(links, c.Name+":"+child.Edge.Name) } container.HostConfig.Links = links return container.WriteHostConfig() }
func (daemon *Daemon) allocateNetwork(container *container.Container) error { controller := daemon.netController if daemon.netController == nil { return nil } // Cleanup any stale sandbox left over due to ungraceful daemon shutdown if err := controller.SandboxDestroy(container.ID); err != nil { 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 } err := daemon.updateContainerNetworkSettings(container, nil) if err != nil { return err } updateSettings = true } // always connect default network first since only default // network mode support link and we need do some setting // on sandbox initialize for link, but the sandbox only be initialized // on first network connecting. defaultNetName := runconfig.DefaultDaemonNetworkMode().NetworkName() if nConf, ok := container.NetworkSettings.Networks[defaultNetName]; ok { cleanOperationalData(nConf) if err := daemon.connectToNetwork(container, defaultNetName, nConf.EndpointSettings, updateSettings); err != nil { return err } } var ( networks []string epConfigs []*network.EndpointSettings ) for n, epConf := range container.NetworkSettings.Networks { if n == defaultNetName { continue } networks = append(networks, n) epConfigs = append(epConfigs, epConf) } for i, epConf := range epConfigs { cleanOperationalData(epConf) if err := daemon.connectToNetwork(container, networks[i], epConf.EndpointSettings, updateSettings); err != nil { return err } } return container.WriteHostConfig() }
func (daemon *Daemon) allocateNetwork(container *container.Container) error { start := time.Now() controller := daemon.netController if daemon.netController == nil { return nil } // Cleanup any stale sandbox left over due to ungraceful daemon shutdown if err := controller.SandboxDestroy(container.ID); err != nil { 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 } daemon.updateContainerNetworkSettings(container, nil) updateSettings = true } // always connect default network first since only default // network mode support link and we need do some setting // on sandbox initialize for link, but the sandbox only be initialized // on first network connecting. defaultNetName := runconfig.DefaultDaemonNetworkMode().NetworkName() if nConf, ok := container.NetworkSettings.Networks[defaultNetName]; ok { cleanOperationalData(nConf) if err := daemon.connectToNetwork(container, defaultNetName, nConf.EndpointSettings, updateSettings); err != nil { return err } } // the intermediate map is necessary because "connectToNetwork" modifies "container.NetworkSettings.Networks" networks := make(map[string]*network.EndpointSettings) for n, epConf := range container.NetworkSettings.Networks { if n == defaultNetName { continue } networks[n] = epConf } for netName, epConf := range networks { cleanOperationalData(epConf) if err := daemon.connectToNetwork(container, netName, epConf.EndpointSettings, updateSettings); err != nil { return err } } if err := container.WriteHostConfig(); err != nil { return err } networkActions.WithValues("allocate").UpdateSince(start) return nil }
func (daemon *Daemon) allocateNetwork(container *container.Container) error { controller := daemon.netController // Cleanup any stale sandbox left over due to ungraceful daemon shutdown if err := controller.SandboxDestroy(container.ID); err != nil { logrus.Errorf("failed to cleanup up stale network sandbox for container %s", container.ID) } updateSettings := false if len(container.NetworkSettings.Networks) == 0 { mode := container.HostConfig.NetworkMode if container.Config.NetworkDisabled || mode.IsContainer() { return nil } networkName := mode.NetworkName() if mode.IsDefault() { networkName = controller.Config().Daemon.DefaultNetwork } if mode.IsUserDefined() { n, err := daemon.FindNetwork(networkName) if err != nil { return err } networkName = n.Name() } container.NetworkSettings.Networks = make(map[string]*networktypes.EndpointSettings) container.NetworkSettings.Networks[networkName] = new(networktypes.EndpointSettings) updateSettings = true } for n := range container.NetworkSettings.Networks { if err := daemon.connectToNetwork(container, n, updateSettings); err != nil { return err } } return container.WriteHostConfig() }
//分配网络的主要代码。 func (daemon *Daemon) allocateNetwork(container *container.Container) error { //controller是一个libnetwork.NetworkController的接口,主要有如下方法: /* type NetworkController interface { // ID provides an unique identity for the controller ID() string // Config method returns the bootup configuration for the controller Config() config.Config // Create a new network. The options parameter carries network specific options. NewNetwork(networkType, name string, options ...NetworkOption) (Network, error) // Networks returns the list of Network(s) managed by this controller. Networks() []Network // WalkNetworks uses the provided function to walk the Network(s) managed by this controller. WalkNetworks(walker NetworkWalker) // NetworkByName returns the Network which has the passed name. If not found, the error ErrNoSuchNetwork is returned. NetworkByName(name string) (Network, error) // NetworkByID returns the Network which has the passed id. If not found, the error ErrNoSuchNetwork is returned. NetworkByID(id string) (Network, error) // NewSandbox cretes a new network sandbox for the passed container id NewSandbox(containerID string, options ...SandboxOption) (Sandbox, error) // Sandboxes returns the list of Sandbox(s) managed by this controller. Sandboxes() []Sandbox // WlakSandboxes uses the provided function to walk the Sandbox(s) managed by this controller. WalkSandboxes(walker SandboxWalker) // SandboxByID returns the Sandbox which has the passed id. If not found, a types.NotFoundError is returned. SandboxByID(id string) (Sandbox, error) // SandboxDestroy destroys a sandbox given a container ID SandboxDestroy(id string) error // Stop network controller Stop() // ReloadCondfiguration updates the controller configuration ReloadConfiguration(cfgOptions ...config.Option) error } */ controller := daemon.netController if daemon.netController == nil { return nil } // Cleanup any stale sandbox left over due to ungraceful daemon shutdown //清除sandbox的相关信息,这个时候容器就没有IP地址了 if err := controller.SandboxDestroy(container.ID); err != nil { 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 } err := daemon.updateContainerNetworkSettings(container, nil) if err != nil { return err } updateSettings = true } //容器可能添加了多个网络,因此需要对每一网络进行连接。 //其中,n代表网络的名字或者id,nConf代表网络的配置。 for n, nConf := range container.NetworkSettings.Networks { if err := daemon.connectToNetwork(container, n, nConf, updateSettings); err != nil { return err } } //更新/var/lib/docker/containers/XXX/hosts文件,即容器的/etc/hosts文件。 return container.WriteHostConfig() }