// set up the watch on the host's /etc/resolv.conf so that we can update container's // live resolv.conf when the network changes on the host func (daemon *Daemon) setupResolvconfWatcher() error { watcher, err := fsnotify.NewWatcher() if err != nil { return err } //this goroutine listens for the events on the watch we add //on the resolv.conf file on the host go func() { for { select { case event := <-watcher.Events: if event.Op&fsnotify.Write == fsnotify.Write { // verify a real change happened before we go further--a file write may have happened // without an actual change to the file updatedResolvConf, newResolvConfHash, err := resolvconf.GetIfChanged() if err != nil { log.Debugf("Error retrieving updated host resolv.conf: %v", err) } else if updatedResolvConf != nil { // because the new host resolv.conf might have localhost nameservers.. updatedResolvConf, modified := resolvconf.RemoveReplaceLocalDns(updatedResolvConf) if modified { // changes have occurred during localhost cleanup: generate an updated hash newHash, err := utils.HashData(bytes.NewReader(updatedResolvConf)) if err != nil { log.Debugf("Error generating hash of new resolv.conf: %v", err) } else { newResolvConfHash = newHash } } log.Debugf("host network resolv.conf changed--walking container list for updates") contList := daemon.containers.List() for _, container := range contList { if err := container.updateResolvConf(updatedResolvConf, newResolvConfHash); err != nil { log.Debugf("Error on resolv.conf update check for container ID: %s: %v", container.ID, err) } } } } case err := <-watcher.Errors: log.Debugf("host resolv.conf notify error: %v", err) } } }() if err := watcher.Add("/etc/resolv.conf"); err != nil { return err } return nil }
func (container *Container) setupContainerDns() error { if container.ResolvConfPath != "" { // check if this is an existing container that needs DNS update: if container.UpdateDns { // read the host's resolv.conf, get the hash and call updateResolvConf log.Debugf("Check container (%s) for update to resolv.conf - UpdateDns flag was set", container.ID) latestResolvConf, latestHash := resolvconf.GetLastModified() // because the new host resolv.conf might have localhost nameservers.. updatedResolvConf, modified := resolvconf.RemoveReplaceLocalDns(latestResolvConf) if modified { // changes have occurred during resolv.conf localhost cleanup: generate an updated hash newHash, err := utils.HashData(bytes.NewReader(updatedResolvConf)) if err != nil { return err } latestHash = newHash } if err := container.updateResolvConf(updatedResolvConf, latestHash); err != nil { return err } // successful update of the restarting container; set the flag off container.UpdateDns = false } return nil } var ( config = container.hostConfig daemon = container.daemon ) resolvConf, err := resolvconf.Get() if err != nil { return err } container.ResolvConfPath, err = container.getRootResourcePath("resolv.conf") if err != nil { return err } if config.NetworkMode != "host" { // check configurations for any container/daemon dns settings if len(config.Dns) > 0 || len(daemon.config.Dns) > 0 || len(config.DnsSearch) > 0 || len(daemon.config.DnsSearch) > 0 { var ( dns = resolvconf.GetNameservers(resolvConf) dnsSearch = resolvconf.GetSearchDomains(resolvConf) ) if len(config.Dns) > 0 { dns = config.Dns } else if len(daemon.config.Dns) > 0 { dns = daemon.config.Dns } if len(config.DnsSearch) > 0 { dnsSearch = config.DnsSearch } else if len(daemon.config.DnsSearch) > 0 { dnsSearch = daemon.config.DnsSearch } return resolvconf.Build(container.ResolvConfPath, dns, dnsSearch) } // replace any localhost/127.* nameservers resolvConf, _ = resolvconf.RemoveReplaceLocalDns(resolvConf) } //get a sha256 hash of the resolv conf at this point so we can check //for changes when the host resolv.conf changes (e.g. network update) resolvHash, err := utils.HashData(bytes.NewReader(resolvConf)) if err != nil { return err } resolvHashFile := container.ResolvConfPath + ".hash" if err = ioutil.WriteFile(resolvHashFile, []byte(resolvHash), 0644); err != nil { return err } return ioutil.WriteFile(container.ResolvConfPath, resolvConf, 0644) }