github.com/moby/docker@v26.1.3+incompatible/cmd/dockerd/options.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 8 "github.com/containerd/log" 9 "github.com/docker/docker/daemon/config" 10 "github.com/docker/docker/opts" 11 "github.com/docker/docker/pkg/homedir" 12 "github.com/docker/go-connections/tlsconfig" 13 "github.com/spf13/pflag" 14 ) 15 16 const ( 17 // DefaultCaFile is the default filename for the CA pem file 18 DefaultCaFile = "ca.pem" 19 // DefaultKeyFile is the default filename for the key pem file 20 DefaultKeyFile = "key.pem" 21 // DefaultCertFile is the default filename for the cert pem file 22 DefaultCertFile = "cert.pem" 23 // FlagTLSVerify is the flag name for the TLS verification option 24 FlagTLSVerify = "tlsverify" 25 // FlagTLS is the flag name for the TLS option 26 FlagTLS = "tls" 27 // DefaultTLSValue is the default value used for setting the tls option for tcp connections 28 DefaultTLSValue = false 29 ) 30 31 var ( 32 // The configDir (and "DOCKER_CONFIG" environment variable) is now only used 33 // for the default location for TLS certificates to secure the daemon API. 34 // It is a leftover from when the "docker" and "dockerd" CLI shared the 35 // same binary, allowing the DOCKER_CONFIG environment variable to set 36 // the location for certificates to be used by both. 37 // 38 // We need to change this, as there's various issues: 39 // 40 // - DOCKER_CONFIG only affects TLS certificates, but does not change the 41 // location for the actual *daemon configuration* (which defaults to 42 // "/etc/docker/daemon.json"). 43 // - If no value is set, configDir uses "~/.docker/" as default, but does 44 // not take $XDG_CONFIG_HOME into account (it uses pkg/homedir.Get, which 45 // is not XDG_CONFIG_HOME-aware). 46 // - Using the home directory can be problematic in cases where the CLI and 47 // daemon actually live on the same host; if DOCKER_CONFIG is set to set 48 // the "docker" CLI configuration path (and if the daemon shares that 49 // environment variable, e.g. "sudo -E dockerd"), the daemon may create 50 // the "~/.docker/" directory, but now the directory may be owned by "root". 51 // 52 // We should: 53 // 54 // - deprecate DOCKER_CONFIG for the daemon 55 // - decide where the TLS certs should live by default ("/etc/docker/"?) 56 // - look at "when" (and when _not_) XDG_CONFIG_HOME should be used. Its 57 // needed for rootless, but perhaps could be used for non-rootless(?) 58 // - When changing the location for TLS config, (ideally) they should 59 // live in a directory separate from "non-sensitive" (configuration-) 60 // files, so that general configuration can be shared (dotfiles repo 61 // etc) separate from "sensitive" config (TLS certificates). 62 // 63 // TODO(thaJeztah): deprecate DOCKER_CONFIG and re-design daemon config locations. See https://github.com/moby/moby/issues/44640 64 configDir = os.Getenv("DOCKER_CONFIG") 65 configFileDir = ".docker" 66 dockerCertPath = os.Getenv("DOCKER_CERT_PATH") 67 dockerTLSVerify = os.Getenv("DOCKER_TLS_VERIFY") != "" 68 ) 69 70 type daemonOptions struct { 71 configFile string 72 daemonConfig *config.Config 73 flags *pflag.FlagSet 74 Debug bool 75 Hosts []string 76 LogLevel string 77 LogFormat string 78 TLS bool 79 TLSVerify bool 80 TLSOptions *tlsconfig.Options 81 Validate bool 82 } 83 84 // defaultCertPath uses $DOCKER_CONFIG or ~/.docker, and does not look up 85 // $XDG_CONFIG_HOME. See the comment on configDir above for further details. 86 func defaultCertPath() string { 87 if configDir == "" { 88 // Set the default path if DOCKER_CONFIG is not set. 89 configDir = filepath.Join(homedir.Get(), configFileDir) 90 } 91 return configDir 92 } 93 94 // newDaemonOptions returns a new daemonFlags 95 func newDaemonOptions(config *config.Config) *daemonOptions { 96 return &daemonOptions{ 97 daemonConfig: config, 98 } 99 } 100 101 // installFlags adds flags for the common options on the FlagSet 102 func (o *daemonOptions) installFlags(flags *pflag.FlagSet) { 103 if dockerCertPath == "" { 104 dockerCertPath = defaultCertPath() 105 } 106 107 flags.BoolVarP(&o.Debug, "debug", "D", false, "Enable debug mode") 108 flags.BoolVar(&o.Validate, "validate", false, "Validate daemon configuration and exit") 109 flags.StringVarP(&o.LogLevel, "log-level", "l", "info", `Set the logging level ("debug"|"info"|"warn"|"error"|"fatal")`) 110 flags.StringVar(&o.LogFormat, "log-format", string(log.TextFormat), fmt.Sprintf(`Set the logging format ("%s"|"%s")`, log.TextFormat, log.JSONFormat)) 111 flags.BoolVar(&o.TLS, FlagTLS, DefaultTLSValue, "Use TLS; implied by --tlsverify") 112 flags.BoolVar(&o.TLSVerify, FlagTLSVerify, dockerTLSVerify || DefaultTLSValue, "Use TLS and verify the remote") 113 114 // TODO(thaJeztah): set default TLSOptions in config.New() 115 o.TLSOptions = &tlsconfig.Options{} 116 tlsOptions := o.TLSOptions 117 flags.StringVar(&tlsOptions.CAFile, "tlscacert", filepath.Join(dockerCertPath, DefaultCaFile), "Trust certs signed only by this CA") 118 flags.StringVar(&tlsOptions.CertFile, "tlscert", filepath.Join(dockerCertPath, DefaultCertFile), "Path to TLS certificate file") 119 flags.StringVar(&tlsOptions.KeyFile, "tlskey", filepath.Join(dockerCertPath, DefaultKeyFile), "Path to TLS key file") 120 121 hostOpt := opts.NewNamedListOptsRef("hosts", &o.Hosts, opts.ValidateHost) 122 flags.VarP(hostOpt, "host", "H", "Daemon socket(s) to connect to") 123 } 124 125 // setDefaultOptions sets default values for options after flag parsing is 126 // complete 127 func (o *daemonOptions) setDefaultOptions() { 128 // Regardless of whether the user sets it to true or false, if they 129 // specify --tlsverify at all then we need to turn on TLS 130 // TLSVerify can be true even if not set due to DOCKER_TLS_VERIFY env var, so we need 131 // to check that here as well 132 if o.flags.Changed(FlagTLSVerify) || o.TLSVerify { 133 o.TLS = true 134 } 135 136 if o.TLS && !o.flags.Changed(FlagTLSVerify) { 137 // Enable tls verification unless explicitly disabled 138 o.TLSVerify = true 139 } 140 141 if !o.TLS { 142 o.TLSOptions = nil 143 } else { 144 o.TLSOptions.InsecureSkipVerify = !o.TLSVerify 145 146 // Reset CertFile and KeyFile to empty string if the user did not specify 147 // the respective flags and the respective default files were not found. 148 if !o.flags.Changed("tlscert") { 149 if _, err := os.Stat(o.TLSOptions.CertFile); os.IsNotExist(err) { 150 o.TLSOptions.CertFile = "" 151 } 152 } 153 if !o.flags.Changed("tlskey") { 154 if _, err := os.Stat(o.TLSOptions.KeyFile); os.IsNotExist(err) { 155 o.TLSOptions.KeyFile = "" 156 } 157 } 158 } 159 }