diff --git a/components/engine/daemon/config/config.go b/components/engine/daemon/config/config.go index 6cda223a11..3aa8703880 100644 --- a/components/engine/daemon/config/config.go +++ b/components/engine/daemon/config/config.go @@ -75,6 +75,8 @@ type commonBridgeConfig struct { type NetworkConfig struct { // Default address pools for docker networks DefaultAddressPools opts.PoolsOpt `json:"default-address-pools,omitempty"` + // NetworkControlPlaneMTU allows to specify the control plane MTU, this will allow to optimize the network use in some components + NetworkControlPlaneMTU int `json:"network-control-plane-mtu,omitempty"` } // CommonTLSOptions defines TLS configuration for the daemon server. @@ -192,8 +194,6 @@ type CommonConfig struct { // Exposed node Generic Resources // e.g: ["orange=red", "orange=green", "orange=blue", "apple=3"] NodeGenericResources []string `json:"node-generic-resources,omitempty"` - // NetworkControlPlaneMTU allows to specify the control plane MTU, this will allow to optimize the network use in some components - NetworkControlPlaneMTU int `json:"network-control-plane-mtu,omitempty"` // ContainerAddr is the address used to connect to containerd if we're // not starting it ourselves diff --git a/components/engine/daemon/config/config_common_unix.go b/components/engine/daemon/config/config_common_unix.go index 4bdf758869..0a862d3b50 100644 --- a/components/engine/daemon/config/config_common_unix.go +++ b/components/engine/daemon/config/config_common_unix.go @@ -69,3 +69,9 @@ func (conf *Config) GetInitPath() string { } return DefaultInitBinary } + +// GetResolvConf returns the appropriate resolv.conf +// Check setupResolvConf on how this is selected +func (conf *Config) GetResolvConf() string { + return conf.ResolvConf +} diff --git a/components/engine/daemon/config/config_unix.go b/components/engine/daemon/config/config_unix.go index 1970928f9b..5ed6abd89e 100644 --- a/components/engine/daemon/config/config_unix.go +++ b/components/engine/daemon/config/config_unix.go @@ -37,6 +37,8 @@ type Config struct { ShmSize opts.MemBytes `json:"default-shm-size,omitempty"` NoNewPrivileges bool `json:"no-new-privileges,omitempty"` IpcMode string `json:"default-ipc-mode,omitempty"` + // ResolvConf is the path to the configuration of the host resolver + ResolvConf string `json:"resolv-conf,omitempty"` } // BridgeConfig stores all the bridge driver specific diff --git a/components/engine/daemon/container_operations.go b/components/engine/daemon/container_operations.go index df84f88f3f..909c7ccb27 100644 --- a/components/engine/daemon/container_operations.go +++ b/components/engine/daemon/container_operations.go @@ -63,21 +63,13 @@ func (daemon *Daemon) buildSandboxOptions(container *container.Container) ([]lib if container.HostConfig.NetworkMode.IsHost() { sboxOptions = append(sboxOptions, libnetwork.OptionUseDefaultSandbox()) - if len(container.HostConfig.ExtraHosts) == 0 { - sboxOptions = append(sboxOptions, libnetwork.OptionOriginHostsPath("/etc/hosts")) - } - if len(container.HostConfig.DNS) == 0 && len(daemon.configStore.DNS) == 0 && - len(container.HostConfig.DNSSearch) == 0 && len(daemon.configStore.DNSSearch) == 0 && - len(container.HostConfig.DNSOptions) == 0 && len(daemon.configStore.DNSOptions) == 0 { - sboxOptions = append(sboxOptions, libnetwork.OptionOriginResolvConfPath("/etc/resolv.conf")) - } } else { // OptionUseExternalKey is mandatory for userns support. // But optional for non-userns support sboxOptions = append(sboxOptions, libnetwork.OptionUseExternalKey()) } - if err = setupPathsAndSandboxOptions(container, &sboxOptions); err != nil { + if err = daemon.setupPathsAndSandboxOptions(container, &sboxOptions); err != nil { return nil, err } diff --git a/components/engine/daemon/container_operations_unix.go b/components/engine/daemon/container_operations_unix.go index bc7ee45233..e66030d9c5 100644 --- a/components/engine/daemon/container_operations_unix.go +++ b/components/engine/daemon/container_operations_unix.go @@ -369,9 +369,17 @@ func (daemon *Daemon) isNetworkHotPluggable() bool { return true } -func setupPathsAndSandboxOptions(container *container.Container, sboxOptions *[]libnetwork.SandboxOption) error { +func (daemon *Daemon) setupPathsAndSandboxOptions(container *container.Container, sboxOptions *[]libnetwork.SandboxOption) error { var err error + if container.HostConfig.NetworkMode.IsHost() { + // Point to the host files, so that will be copied into the container running in host mode + *sboxOptions = append(*sboxOptions, libnetwork.OptionOriginHostsPath("/etc/hosts")) + *sboxOptions = append(*sboxOptions, libnetwork.OptionOriginResolvConfPath("/etc/resolv.conf")) + } else { + *sboxOptions = append(*sboxOptions, libnetwork.OptionOriginResolvConfPath(daemon.configStore.GetResolvConf())) + } + container.HostsPath, err = container.GetRootResourcePath("hosts") if err != nil { return err diff --git a/components/engine/daemon/container_operations_windows.go b/components/engine/daemon/container_operations_windows.go index 562528a8ef..349d3a1566 100644 --- a/components/engine/daemon/container_operations_windows.go +++ b/components/engine/daemon/container_operations_windows.go @@ -155,7 +155,7 @@ func (daemon *Daemon) isNetworkHotPluggable() bool { return true } -func setupPathsAndSandboxOptions(container *container.Container, sboxOptions *[]libnetwork.SandboxOption) error { +func (daemon *Daemon) setupPathsAndSandboxOptions(container *container.Container, sboxOptions *[]libnetwork.SandboxOption) error { return nil } diff --git a/components/engine/daemon/daemon.go b/components/engine/daemon/daemon.go index 119fac2a0a..c579766e95 100644 --- a/components/engine/daemon/daemon.go +++ b/components/engine/daemon/daemon.go @@ -581,6 +581,9 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe // Do we have a disabled network? config.DisableBridge = isBridgeNetworkDisabled(config) + // Setup the resolv.conf + setupResolvConf(config) + // Verify the platform is supported as a daemon if !platformSupported { return nil, errSystemNotSupported diff --git a/components/engine/daemon/daemon_linux.go b/components/engine/daemon/daemon_linux.go index 7cb6727534..6a5790b4fc 100644 --- a/components/engine/daemon/daemon_linux.go +++ b/components/engine/daemon/daemon_linux.go @@ -8,12 +8,19 @@ import ( "regexp" "strings" + "github.com/docker/docker/daemon/config" + "github.com/docker/docker/internal/procfs" "github.com/docker/docker/pkg/fileutils" "github.com/docker/docker/pkg/mount" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) +const ( + defaultResolvConf = "/etc/resolv.conf" + alternateResolvConf = "/run/systemd/resolve/resolv.conf" +) + // On Linux, plugins use a static path for storing execution state, // instead of deriving path from daemon's exec-root. This is because // plugin socket files are created here and they cannot exceed max @@ -131,3 +138,30 @@ func shouldUnmountRoot(root string, info *mount.Info) bool { } return hasMountinfoOption(info.Optional, sharedPropagationOption) } + +// setupResolvConf sets the appropriate resolv.conf file if not specified +// When systemd-resolved is running the default /etc/resolv.conf points to +// localhost. In this case fetch the alternative config file that is in a +// different path so that containers can use it +// In all the other cases fallback to the default one +func setupResolvConf(config *config.Config) { + if config.ResolvConf != "" { + return + } + + config.ResolvConf = defaultResolvConf + pids, err := procfs.PidOf("systemd-resolved") + if err != nil { + logrus.Errorf("unable to check systemd-resolved status: %s", err) + return + } + if len(pids) > 0 && pids[0] > 0 { + _, err := os.Stat(alternateResolvConf) + if err == nil { + logrus.Infof("systemd-resolved is running, so using resolvconf: %s", alternateResolvConf) + config.ResolvConf = alternateResolvConf + return + } + logrus.Infof("systemd-resolved is running, but %s is not present, fallback to %s", alternateResolvConf, defaultResolvConf) + } +} diff --git a/components/engine/daemon/daemon_unsupported.go b/components/engine/daemon/daemon_unsupported.go index ee680b6411..6d8ac6224b 100644 --- a/components/engine/daemon/daemon_unsupported.go +++ b/components/engine/daemon/daemon_unsupported.go @@ -1,5 +1,9 @@ // +build !linux,!freebsd,!windows package daemon // import "github.com/docker/docker/daemon" +import "github.com/docker/docker/daemon/config" const platformSupported = false + +func setupResolvConf(config *config.Config) { +} diff --git a/components/engine/daemon/daemon_windows.go b/components/engine/daemon/daemon_windows.go index 1f801032df..98f89f39d3 100644 --- a/components/engine/daemon/daemon_windows.go +++ b/components/engine/daemon/daemon_windows.go @@ -653,3 +653,6 @@ func (daemon *Daemon) loadRuntimes() error { func (daemon *Daemon) initRuntimes(_ map[string]types.Runtime) error { return nil } + +func setupResolvConf(config *config.Config) { +}