github.com/rish1988/moby@v25.0.2+incompatible/daemon/config/config_linux.go (about)

     1  package config // import "github.com/docker/docker/daemon/config"
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net"
     7  	"os/exec"
     8  	"path/filepath"
     9  
    10  	"github.com/containerd/cgroups/v3"
    11  	"github.com/containerd/log"
    12  	"github.com/docker/docker/api/types/container"
    13  	"github.com/docker/docker/api/types/system"
    14  	"github.com/docker/docker/libnetwork/drivers/bridge"
    15  	"github.com/docker/docker/opts"
    16  	"github.com/docker/docker/pkg/homedir"
    17  	"github.com/docker/docker/pkg/rootless"
    18  	units "github.com/docker/go-units"
    19  	"github.com/pkg/errors"
    20  )
    21  
    22  const (
    23  	// DefaultIpcMode is default for container's IpcMode, if not set otherwise
    24  	DefaultIpcMode = container.IPCModePrivate
    25  
    26  	// DefaultCgroupNamespaceMode is the default mode for containers cgroup namespace when using cgroups v2.
    27  	DefaultCgroupNamespaceMode = container.CgroupnsModePrivate
    28  
    29  	// DefaultCgroupV1NamespaceMode is the default mode for containers cgroup namespace when using cgroups v1.
    30  	DefaultCgroupV1NamespaceMode = container.CgroupnsModeHost
    31  
    32  	// StockRuntimeName is the reserved name/alias used to represent the
    33  	// OCI runtime being shipped with the docker daemon package.
    34  	StockRuntimeName = "runc"
    35  
    36  	// minAPIVersion represents Minimum REST API version supported
    37  	minAPIVersion = "1.12"
    38  
    39  	// userlandProxyBinary is the name of the userland-proxy binary.
    40  	// In rootless-mode, [rootless.RootlessKitDockerProxyBinary] is used instead.
    41  	userlandProxyBinary = "docker-proxy"
    42  )
    43  
    44  // BridgeConfig stores all the parameters for both the bridge driver and the default bridge network.
    45  type BridgeConfig struct {
    46  	DefaultBridgeConfig
    47  
    48  	EnableIPTables      bool   `json:"iptables,omitempty"`
    49  	EnableIP6Tables     bool   `json:"ip6tables,omitempty"`
    50  	EnableIPForward     bool   `json:"ip-forward,omitempty"`
    51  	EnableIPMasq        bool   `json:"ip-masq,omitempty"`
    52  	EnableUserlandProxy bool   `json:"userland-proxy,omitempty"`
    53  	UserlandProxyPath   string `json:"userland-proxy-path,omitempty"`
    54  }
    55  
    56  // DefaultBridgeConfig stores all the parameters for the default bridge network.
    57  type DefaultBridgeConfig struct {
    58  	commonBridgeConfig
    59  
    60  	// Fields below here are platform specific.
    61  	EnableIPv6                  bool   `json:"ipv6,omitempty"`
    62  	FixedCIDRv6                 string `json:"fixed-cidr-v6,omitempty"`
    63  	MTU                         int    `json:"mtu,omitempty"`
    64  	DefaultIP                   net.IP `json:"ip,omitempty"`
    65  	IP                          string `json:"bip,omitempty"`
    66  	DefaultGatewayIPv4          net.IP `json:"default-gateway,omitempty"`
    67  	DefaultGatewayIPv6          net.IP `json:"default-gateway-v6,omitempty"`
    68  	InterContainerCommunication bool   `json:"icc,omitempty"`
    69  }
    70  
    71  // Config defines the configuration of a docker daemon.
    72  // It includes json tags to deserialize configuration from a file
    73  // using the same names that the flags in the command line uses.
    74  type Config struct {
    75  	CommonConfig
    76  
    77  	// Fields below here are platform specific.
    78  	Runtimes             map[string]system.Runtime `json:"runtimes,omitempty"`
    79  	DefaultInitBinary    string                    `json:"default-init,omitempty"`
    80  	CgroupParent         string                    `json:"cgroup-parent,omitempty"`
    81  	EnableSelinuxSupport bool                      `json:"selinux-enabled,omitempty"`
    82  	RemappedRoot         string                    `json:"userns-remap,omitempty"`
    83  	Ulimits              map[string]*units.Ulimit  `json:"default-ulimits,omitempty"`
    84  	CPURealtimePeriod    int64                     `json:"cpu-rt-period,omitempty"`
    85  	CPURealtimeRuntime   int64                     `json:"cpu-rt-runtime,omitempty"`
    86  	Init                 bool                      `json:"init,omitempty"`
    87  	InitPath             string                    `json:"init-path,omitempty"`
    88  	SeccompProfile       string                    `json:"seccomp-profile,omitempty"`
    89  	ShmSize              opts.MemBytes             `json:"default-shm-size,omitempty"`
    90  	NoNewPrivileges      bool                      `json:"no-new-privileges,omitempty"`
    91  	IpcMode              string                    `json:"default-ipc-mode,omitempty"`
    92  	CgroupNamespaceMode  string                    `json:"default-cgroupns-mode,omitempty"`
    93  	// ResolvConf is the path to the configuration of the host resolver
    94  	ResolvConf string `json:"resolv-conf,omitempty"`
    95  	Rootless   bool   `json:"rootless,omitempty"`
    96  }
    97  
    98  // GetExecRoot returns the user configured Exec-root
    99  func (conf *Config) GetExecRoot() string {
   100  	return conf.ExecRoot
   101  }
   102  
   103  // GetInitPath returns the configured docker-init path
   104  func (conf *Config) GetInitPath() string {
   105  	if conf.InitPath != "" {
   106  		return conf.InitPath
   107  	}
   108  	if conf.DefaultInitBinary != "" {
   109  		return conf.DefaultInitBinary
   110  	}
   111  	return DefaultInitBinary
   112  }
   113  
   114  // LookupInitPath returns an absolute path to the "docker-init" binary by searching relevant "libexec" directories (per FHS 3.0 & 2.3) followed by PATH
   115  func (conf *Config) LookupInitPath() (string, error) {
   116  	binary := conf.GetInitPath()
   117  	if filepath.IsAbs(binary) {
   118  		return binary, nil
   119  	}
   120  
   121  	for _, dir := range []string{
   122  		// FHS 3.0: "/usr/libexec includes internal binaries that are not intended to be executed directly by users or shell scripts. Applications may use a single subdirectory under /usr/libexec."
   123  		// https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch04s07.html
   124  		"/usr/local/libexec/docker",
   125  		"/usr/libexec/docker",
   126  
   127  		// FHS 2.3: "/usr/lib includes object files, libraries, and internal binaries that are not intended to be executed directly by users or shell scripts."
   128  		// https://refspecs.linuxfoundation.org/FHS_2.3/fhs-2.3.html#USRLIBLIBRARIESFORPROGRAMMINGANDPA
   129  		"/usr/local/lib/docker",
   130  		"/usr/lib/docker",
   131  	} {
   132  		// exec.LookPath has a fast-path short-circuit for paths that contain "/" (skipping the PATH lookup) that then verifies whether the given path is likely to be an actual executable binary (so we invoke that instead of reimplementing the same checks)
   133  		if file, err := exec.LookPath(filepath.Join(dir, binary)); err == nil {
   134  			return file, nil
   135  		}
   136  	}
   137  
   138  	// if we checked all the "libexec" directories and found no matches, fall back to PATH
   139  	return exec.LookPath(binary)
   140  }
   141  
   142  // GetResolvConf returns the appropriate resolv.conf
   143  // Check setupResolvConf on how this is selected
   144  func (conf *Config) GetResolvConf() string {
   145  	return conf.ResolvConf
   146  }
   147  
   148  // IsSwarmCompatible defines if swarm mode can be enabled in this config
   149  func (conf *Config) IsSwarmCompatible() error {
   150  	if conf.LiveRestoreEnabled {
   151  		return fmt.Errorf("--live-restore daemon configuration is incompatible with swarm mode")
   152  	}
   153  	return nil
   154  }
   155  
   156  func verifyDefaultIpcMode(mode string) error {
   157  	const hint = `use "shareable" or "private"`
   158  
   159  	dm := container.IpcMode(mode)
   160  	if !dm.Valid() {
   161  		return fmt.Errorf("default IPC mode setting (%v) is invalid; "+hint, dm)
   162  	}
   163  	if dm != "" && !dm.IsPrivate() && !dm.IsShareable() {
   164  		return fmt.Errorf(`IPC mode "%v" is not supported as default value; `+hint, dm)
   165  	}
   166  	return nil
   167  }
   168  
   169  func verifyDefaultCgroupNsMode(mode string) error {
   170  	cm := container.CgroupnsMode(mode)
   171  	if !cm.Valid() {
   172  		return fmt.Errorf(`default cgroup namespace mode (%v) is invalid; use "host" or "private"`, cm)
   173  	}
   174  
   175  	return nil
   176  }
   177  
   178  // ValidatePlatformConfig checks if any platform-specific configuration settings are invalid.
   179  func (conf *Config) ValidatePlatformConfig() error {
   180  	if conf.EnableUserlandProxy {
   181  		if conf.UserlandProxyPath == "" {
   182  			return errors.New("invalid userland-proxy-path: userland-proxy is enabled, but userland-proxy-path is not set")
   183  		}
   184  		if !filepath.IsAbs(conf.UserlandProxyPath) {
   185  			return errors.New("invalid userland-proxy-path: must be an absolute path: " + conf.UserlandProxyPath)
   186  		}
   187  		// Using exec.LookPath here, because it also produces an error if the
   188  		// given path is not a valid executable or a directory.
   189  		if _, err := exec.LookPath(conf.UserlandProxyPath); err != nil {
   190  			return errors.Wrap(err, "invalid userland-proxy-path")
   191  		}
   192  	}
   193  
   194  	if err := verifyDefaultIpcMode(conf.IpcMode); err != nil {
   195  		return err
   196  	}
   197  
   198  	if err := bridge.ValidateFixedCIDRV6(conf.FixedCIDRv6); err != nil {
   199  		return errors.Wrap(err, "invalid fixed-cidr-v6")
   200  	}
   201  
   202  	return verifyDefaultCgroupNsMode(conf.CgroupNamespaceMode)
   203  }
   204  
   205  // IsRootless returns conf.Rootless on Linux but false on Windows
   206  func (conf *Config) IsRootless() bool {
   207  	return conf.Rootless
   208  }
   209  
   210  func setPlatformDefaults(cfg *Config) error {
   211  	cfg.Ulimits = make(map[string]*units.Ulimit)
   212  	cfg.ShmSize = opts.MemBytes(DefaultShmSize)
   213  	cfg.SeccompProfile = SeccompProfileDefault
   214  	cfg.IpcMode = string(DefaultIpcMode)
   215  	cfg.Runtimes = make(map[string]system.Runtime)
   216  
   217  	if cgroups.Mode() != cgroups.Unified {
   218  		cfg.CgroupNamespaceMode = string(DefaultCgroupV1NamespaceMode)
   219  	} else {
   220  		cfg.CgroupNamespaceMode = string(DefaultCgroupNamespaceMode)
   221  	}
   222  
   223  	if rootless.RunningWithRootlessKit() {
   224  		cfg.Rootless = true
   225  
   226  		var err error
   227  		// use rootlesskit-docker-proxy for exposing the ports in RootlessKit netns to the initial namespace.
   228  		cfg.BridgeConfig.UserlandProxyPath, err = exec.LookPath(rootless.RootlessKitDockerProxyBinary)
   229  		if err != nil {
   230  			return errors.Wrapf(err, "running with RootlessKit, but %s not installed", rootless.RootlessKitDockerProxyBinary)
   231  		}
   232  
   233  		dataHome, err := homedir.GetDataHome()
   234  		if err != nil {
   235  			return err
   236  		}
   237  		runtimeDir, err := homedir.GetRuntimeDir()
   238  		if err != nil {
   239  			return err
   240  		}
   241  
   242  		cfg.Root = filepath.Join(dataHome, "docker")
   243  		cfg.ExecRoot = filepath.Join(runtimeDir, "docker")
   244  		cfg.Pidfile = filepath.Join(runtimeDir, "docker.pid")
   245  	} else {
   246  		var err error
   247  		cfg.BridgeConfig.UserlandProxyPath, err = exec.LookPath(userlandProxyBinary)
   248  		if err != nil {
   249  			// Log, but don't error here. This allows running a daemon with
   250  			// userland-proxy disabled (which does not require the binary
   251  			// to be present).
   252  			//
   253  			// An error is still produced by [Config.ValidatePlatformConfig] if
   254  			// userland-proxy is enabled in the configuration.
   255  			//
   256  			// We log this at "debug" level, as this code is also executed
   257  			// when running "--version", and we don't want to print logs in
   258  			// that case..
   259  			log.G(context.TODO()).WithError(err).Debug("failed to lookup default userland-proxy binary")
   260  		}
   261  		cfg.Root = "/var/lib/docker"
   262  		cfg.ExecRoot = "/var/run/docker"
   263  		cfg.Pidfile = "/var/run/docker.pid"
   264  	}
   265  
   266  	return nil
   267  }