Quellcode durchsuchen

Fixes for resolv.conf

Handle the case of systemd-resolved, and if in place
use a different resolv.conf source.
Set appropriately the option on libnetwork.
Move unix specific code to container_operation_unix

Signed-off-by: Flavio Crisciani <flavio.crisciani@docker.com>
Flavio Crisciani vor 7 Jahren
Ursprung
Commit
e353e7e3f0

+ 2 - 2
daemon/config/config.go

@@ -75,6 +75,8 @@ type commonBridgeConfig struct {
 type NetworkConfig struct {
 type NetworkConfig struct {
 	// Default address pools for docker networks
 	// Default address pools for docker networks
 	DefaultAddressPools opts.PoolsOpt `json:"default-address-pools,omitempty"`
 	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.
 // CommonTLSOptions defines TLS configuration for the daemon server.
@@ -192,8 +194,6 @@ type CommonConfig struct {
 	// Exposed node Generic Resources
 	// Exposed node Generic Resources
 	// e.g: ["orange=red", "orange=green", "orange=blue", "apple=3"]
 	// e.g: ["orange=red", "orange=green", "orange=blue", "apple=3"]
 	NodeGenericResources []string `json:"node-generic-resources,omitempty"`
 	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
 	// ContainerAddr is the address used to connect to containerd if we're
 	// not starting it ourselves
 	// not starting it ourselves

+ 6 - 0
daemon/config/config_common_unix.go

@@ -69,3 +69,9 @@ func (conf *Config) GetInitPath() string {
 	}
 	}
 	return DefaultInitBinary
 	return DefaultInitBinary
 }
 }
+
+// GetResolvConf returns the appropriate resolv.conf
+// Check setupResolvConf on how this is selected
+func (conf *Config) GetResolvConf() string {
+	return conf.ResolvConf
+}

+ 2 - 0
daemon/config/config_unix.go

@@ -37,6 +37,8 @@ type Config struct {
 	ShmSize              opts.MemBytes            `json:"default-shm-size,omitempty"`
 	ShmSize              opts.MemBytes            `json:"default-shm-size,omitempty"`
 	NoNewPrivileges      bool                     `json:"no-new-privileges,omitempty"`
 	NoNewPrivileges      bool                     `json:"no-new-privileges,omitempty"`
 	IpcMode              string                   `json:"default-ipc-mode,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
 // BridgeConfig stores all the bridge driver specific

+ 1 - 9
daemon/container_operations.go

@@ -63,21 +63,13 @@ func (daemon *Daemon) buildSandboxOptions(container *container.Container) ([]lib
 
 
 	if container.HostConfig.NetworkMode.IsHost() {
 	if container.HostConfig.NetworkMode.IsHost() {
 		sboxOptions = append(sboxOptions, libnetwork.OptionUseDefaultSandbox())
 		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 {
 	} else {
 		// OptionUseExternalKey is mandatory for userns support.
 		// OptionUseExternalKey is mandatory for userns support.
 		// But optional for non-userns support
 		// But optional for non-userns support
 		sboxOptions = append(sboxOptions, libnetwork.OptionUseExternalKey())
 		sboxOptions = append(sboxOptions, libnetwork.OptionUseExternalKey())
 	}
 	}
 
 
-	if err = setupPathsAndSandboxOptions(container, &sboxOptions); err != nil {
+	if err = daemon.setupPathsAndSandboxOptions(container, &sboxOptions); err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 
 

+ 9 - 1
daemon/container_operations_unix.go

@@ -369,9 +369,17 @@ func (daemon *Daemon) isNetworkHotPluggable() bool {
 	return true
 	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
 	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")
 	container.HostsPath, err = container.GetRootResourcePath("hosts")
 	if err != nil {
 	if err != nil {
 		return err
 		return err

+ 1 - 1
daemon/container_operations_windows.go

@@ -155,7 +155,7 @@ func (daemon *Daemon) isNetworkHotPluggable() bool {
 	return true
 	return true
 }
 }
 
 
-func setupPathsAndSandboxOptions(container *container.Container, sboxOptions *[]libnetwork.SandboxOption) error {
+func (daemon *Daemon) setupPathsAndSandboxOptions(container *container.Container, sboxOptions *[]libnetwork.SandboxOption) error {
 	return nil
 	return nil
 }
 }
 
 

+ 3 - 0
daemon/daemon.go

@@ -581,6 +581,9 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe
 	// Do we have a disabled network?
 	// Do we have a disabled network?
 	config.DisableBridge = isBridgeNetworkDisabled(config)
 	config.DisableBridge = isBridgeNetworkDisabled(config)
 
 
+	// Setup the resolv.conf
+	setupResolvConf(config)
+
 	// Verify the platform is supported as a daemon
 	// Verify the platform is supported as a daemon
 	if !platformSupported {
 	if !platformSupported {
 		return nil, errSystemNotSupported
 		return nil, errSystemNotSupported

+ 34 - 0
daemon/daemon_linux.go

@@ -8,12 +8,19 @@ import (
 	"regexp"
 	"regexp"
 	"strings"
 	"strings"
 
 
+	"github.com/docker/docker/daemon/config"
+	"github.com/docker/docker/internal/procfs"
 	"github.com/docker/docker/pkg/fileutils"
 	"github.com/docker/docker/pkg/fileutils"
 	"github.com/docker/docker/pkg/mount"
 	"github.com/docker/docker/pkg/mount"
 	"github.com/pkg/errors"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 	"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,
 // On Linux, plugins use a static path for storing execution state,
 // instead of deriving path from daemon's exec-root. This is because
 // instead of deriving path from daemon's exec-root. This is because
 // plugin socket files are created here and they cannot exceed max
 // 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)
 	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)
+	}
+}

+ 4 - 0
daemon/daemon_unsupported.go

@@ -1,5 +1,9 @@
 // +build !linux,!freebsd,!windows
 // +build !linux,!freebsd,!windows
 
 
 package daemon // import "github.com/docker/docker/daemon"
 package daemon // import "github.com/docker/docker/daemon"
+import "github.com/docker/docker/daemon/config"
 
 
 const platformSupported = false
 const platformSupported = false
+
+func setupResolvConf(config *config.Config) {
+}

+ 3 - 0
daemon/daemon_windows.go

@@ -653,3 +653,6 @@ func (daemon *Daemon) loadRuntimes() error {
 func (daemon *Daemon) initRuntimes(_ map[string]types.Runtime) error {
 func (daemon *Daemon) initRuntimes(_ map[string]types.Runtime) error {
 	return nil
 	return nil
 }
 }
+
+func setupResolvConf(config *config.Config) {
+}