config_linux.go 9.9 KB

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