github.com/adityamillind98/moby@v23.0.0-rc.4+incompatible/daemon/info.go (about) 1 package daemon // import "github.com/docker/docker/daemon" 2 3 import ( 4 "fmt" 5 "os" 6 "runtime" 7 "strings" 8 "time" 9 10 "github.com/docker/docker/api" 11 "github.com/docker/docker/api/types" 12 "github.com/docker/docker/cli/debug" 13 "github.com/docker/docker/daemon/config" 14 "github.com/docker/docker/daemon/logger" 15 "github.com/docker/docker/dockerversion" 16 "github.com/docker/docker/pkg/fileutils" 17 "github.com/docker/docker/pkg/parsers/kernel" 18 "github.com/docker/docker/pkg/parsers/operatingsystem" 19 "github.com/docker/docker/pkg/platform" 20 "github.com/docker/docker/pkg/sysinfo" 21 "github.com/docker/docker/pkg/system" 22 "github.com/docker/docker/registry" 23 metrics "github.com/docker/go-metrics" 24 "github.com/opencontainers/selinux/go-selinux" 25 "github.com/sirupsen/logrus" 26 ) 27 28 // SystemInfo returns information about the host server the daemon is running on. 29 func (daemon *Daemon) SystemInfo() *types.Info { 30 defer metrics.StartTimer(hostInfoFunctions.WithValues("system_info"))() 31 32 sysInfo := daemon.RawSysInfo() 33 34 v := &types.Info{ 35 ID: daemon.id, 36 Images: daemon.imageService.CountImages(), 37 IPv4Forwarding: !sysInfo.IPv4ForwardingDisabled, 38 BridgeNfIptables: !sysInfo.BridgeNFCallIPTablesDisabled, 39 BridgeNfIP6tables: !sysInfo.BridgeNFCallIP6TablesDisabled, 40 Name: hostName(), 41 SystemTime: time.Now().Format(time.RFC3339Nano), 42 LoggingDriver: daemon.defaultLogConfig.Type, 43 KernelVersion: kernelVersion(), 44 OperatingSystem: operatingSystem(), 45 OSVersion: osVersion(), 46 IndexServerAddress: registry.IndexServer, 47 OSType: platform.OSType, 48 Architecture: platform.Architecture, 49 RegistryConfig: daemon.registryService.ServiceConfig(), 50 NCPU: sysinfo.NumCPU(), 51 MemTotal: memInfo().MemTotal, 52 GenericResources: daemon.genericResources, 53 DockerRootDir: daemon.configStore.Root, 54 Labels: daemon.configStore.Labels, 55 ExperimentalBuild: daemon.configStore.Experimental, 56 ServerVersion: dockerversion.Version, 57 HTTPProxy: config.MaskCredentials(getConfigOrEnv(daemon.configStore.HTTPProxy, "HTTP_PROXY", "http_proxy")), 58 HTTPSProxy: config.MaskCredentials(getConfigOrEnv(daemon.configStore.HTTPSProxy, "HTTPS_PROXY", "https_proxy")), 59 NoProxy: getConfigOrEnv(daemon.configStore.NoProxy, "NO_PROXY", "no_proxy"), 60 LiveRestoreEnabled: daemon.configStore.LiveRestoreEnabled, 61 Isolation: daemon.defaultIsolation, 62 } 63 64 daemon.fillContainerStates(v) 65 daemon.fillDebugInfo(v) 66 daemon.fillAPIInfo(v) 67 // Retrieve platform specific info 68 daemon.fillPlatformInfo(v, sysInfo) 69 daemon.fillDriverInfo(v) 70 daemon.fillPluginsInfo(v) 71 daemon.fillSecurityOptions(v, sysInfo) 72 daemon.fillLicense(v) 73 daemon.fillDefaultAddressPools(v) 74 75 return v 76 } 77 78 // SystemVersion returns version information about the daemon. 79 func (daemon *Daemon) SystemVersion() types.Version { 80 defer metrics.StartTimer(hostInfoFunctions.WithValues("system_version"))() 81 82 kernelVersion := kernelVersion() 83 84 v := types.Version{ 85 Components: []types.ComponentVersion{ 86 { 87 Name: "Engine", 88 Version: dockerversion.Version, 89 Details: map[string]string{ 90 "GitCommit": dockerversion.GitCommit, 91 "ApiVersion": api.DefaultVersion, 92 "MinAPIVersion": api.MinVersion, 93 "GoVersion": runtime.Version(), 94 "Os": runtime.GOOS, 95 "Arch": runtime.GOARCH, 96 "BuildTime": dockerversion.BuildTime, 97 "KernelVersion": kernelVersion, 98 "Experimental": fmt.Sprintf("%t", daemon.configStore.Experimental), 99 }, 100 }, 101 }, 102 103 // Populate deprecated fields for older clients 104 Version: dockerversion.Version, 105 GitCommit: dockerversion.GitCommit, 106 APIVersion: api.DefaultVersion, 107 MinAPIVersion: api.MinVersion, 108 GoVersion: runtime.Version(), 109 Os: runtime.GOOS, 110 Arch: runtime.GOARCH, 111 BuildTime: dockerversion.BuildTime, 112 KernelVersion: kernelVersion, 113 Experimental: daemon.configStore.Experimental, 114 } 115 116 v.Platform.Name = dockerversion.PlatformName 117 118 daemon.fillPlatformVersion(&v) 119 return v 120 } 121 122 func (daemon *Daemon) fillDriverInfo(v *types.Info) { 123 const warnMsg = ` 124 WARNING: The %s storage-driver is deprecated, and will be removed in a future release. 125 Refer to the documentation for more information: https://docs.docker.com/go/storage-driver/` 126 127 switch daemon.graphDriver { 128 case "aufs", "devicemapper", "overlay": 129 v.Warnings = append(v.Warnings, fmt.Sprintf(warnMsg, daemon.graphDriver)) 130 } 131 132 v.Driver = daemon.graphDriver 133 v.DriverStatus = daemon.imageService.LayerStoreStatus() 134 135 fillDriverWarnings(v) 136 } 137 138 func (daemon *Daemon) fillPluginsInfo(v *types.Info) { 139 v.Plugins = types.PluginsInfo{ 140 Volume: daemon.volumes.GetDriverList(), 141 Network: daemon.GetNetworkDriverList(), 142 143 // The authorization plugins are returned in the order they are 144 // used as they constitute a request/response modification chain. 145 Authorization: daemon.configStore.AuthorizationPlugins, 146 Log: logger.ListDrivers(), 147 } 148 } 149 150 func (daemon *Daemon) fillSecurityOptions(v *types.Info, sysInfo *sysinfo.SysInfo) { 151 var securityOptions []string 152 if sysInfo.AppArmor { 153 securityOptions = append(securityOptions, "name=apparmor") 154 } 155 if sysInfo.Seccomp && supportsSeccomp { 156 if daemon.seccompProfilePath != config.SeccompProfileDefault { 157 v.Warnings = append(v.Warnings, "WARNING: daemon is not using the default seccomp profile") 158 } 159 securityOptions = append(securityOptions, "name=seccomp,profile="+daemon.seccompProfilePath) 160 } 161 if selinux.GetEnabled() { 162 securityOptions = append(securityOptions, "name=selinux") 163 } 164 if rootIDs := daemon.idMapping.RootPair(); rootIDs.UID != 0 || rootIDs.GID != 0 { 165 securityOptions = append(securityOptions, "name=userns") 166 } 167 if daemon.Rootless() { 168 securityOptions = append(securityOptions, "name=rootless") 169 } 170 if daemon.cgroupNamespacesEnabled(sysInfo) { 171 securityOptions = append(securityOptions, "name=cgroupns") 172 } 173 174 v.SecurityOptions = securityOptions 175 } 176 177 func (daemon *Daemon) fillContainerStates(v *types.Info) { 178 cRunning, cPaused, cStopped := stateCtr.get() 179 v.Containers = cRunning + cPaused + cStopped 180 v.ContainersPaused = cPaused 181 v.ContainersRunning = cRunning 182 v.ContainersStopped = cStopped 183 } 184 185 // fillDebugInfo sets the current debugging state of the daemon, and additional 186 // debugging information, such as the number of Go-routines, and file descriptors. 187 // 188 // Note that this currently always collects the information, but the CLI only 189 // prints it if the daemon has debug enabled. We should consider to either make 190 // this information optional (cli to request "with debugging information"), or 191 // only collect it if the daemon has debug enabled. For the CLI code, see 192 // https://github.com/docker/cli/blob/v20.10.12/cli/command/system/info.go#L239-L244 193 func (daemon *Daemon) fillDebugInfo(v *types.Info) { 194 v.Debug = debug.IsEnabled() 195 v.NFd = fileutils.GetTotalUsedFds() 196 v.NGoroutines = runtime.NumGoroutine() 197 v.NEventsListener = daemon.EventsService.SubscribersCount() 198 } 199 200 func (daemon *Daemon) fillAPIInfo(v *types.Info) { 201 const warn string = ` 202 Access to the remote API is equivalent to root access on the host. Refer 203 to the 'Docker daemon attack surface' section in the documentation for 204 more information: https://docs.docker.com/go/attack-surface/` 205 206 cfg := daemon.configStore 207 for _, host := range cfg.Hosts { 208 // cnf.Hosts is normalized during startup, so should always have a scheme/proto 209 h := strings.SplitN(host, "://", 2) 210 proto := h[0] 211 addr := h[1] 212 if proto != "tcp" { 213 continue 214 } 215 if cfg.TLS == nil || !*cfg.TLS { 216 v.Warnings = append(v.Warnings, fmt.Sprintf("WARNING: API is accessible on http://%s without encryption.%s", addr, warn)) 217 continue 218 } 219 if cfg.TLSVerify == nil || !*cfg.TLSVerify { 220 v.Warnings = append(v.Warnings, fmt.Sprintf("WARNING: API is accessible on https://%s without TLS client verification.%s", addr, warn)) 221 continue 222 } 223 } 224 } 225 226 func (daemon *Daemon) fillDefaultAddressPools(v *types.Info) { 227 for _, pool := range daemon.configStore.DefaultAddressPools.Value() { 228 v.DefaultAddressPools = append(v.DefaultAddressPools, types.NetworkAddressPool{ 229 Base: pool.Base, 230 Size: pool.Size, 231 }) 232 } 233 } 234 235 func hostName() string { 236 hostname := "" 237 if hn, err := os.Hostname(); err != nil { 238 logrus.Warnf("Could not get hostname: %v", err) 239 } else { 240 hostname = hn 241 } 242 return hostname 243 } 244 245 func kernelVersion() string { 246 var kernelVersion string 247 if kv, err := kernel.GetKernelVersion(); err != nil { 248 logrus.Warnf("Could not get kernel version: %v", err) 249 } else { 250 kernelVersion = kv.String() 251 } 252 return kernelVersion 253 } 254 255 func memInfo() *system.MemInfo { 256 memInfo, err := system.ReadMemInfo() 257 if err != nil { 258 logrus.Errorf("Could not read system memory info: %v", err) 259 memInfo = &system.MemInfo{} 260 } 261 return memInfo 262 } 263 264 func operatingSystem() (operatingSystem string) { 265 defer metrics.StartTimer(hostInfoFunctions.WithValues("operating_system"))() 266 267 if s, err := operatingsystem.GetOperatingSystem(); err != nil { 268 logrus.Warnf("Could not get operating system name: %v", err) 269 } else { 270 operatingSystem = s 271 } 272 if inContainer, err := operatingsystem.IsContainerized(); err != nil { 273 logrus.Errorf("Could not determine if daemon is containerized: %v", err) 274 operatingSystem += " (error determining if containerized)" 275 } else if inContainer { 276 operatingSystem += " (containerized)" 277 } 278 279 return operatingSystem 280 } 281 282 func osVersion() (version string) { 283 defer metrics.StartTimer(hostInfoFunctions.WithValues("os_version"))() 284 285 version, err := operatingsystem.GetOperatingSystemVersion() 286 if err != nil { 287 logrus.Warnf("Could not get operating system version: %v", err) 288 } 289 290 return version 291 } 292 293 func getEnvAny(names ...string) string { 294 for _, n := range names { 295 if val := os.Getenv(n); val != "" { 296 return val 297 } 298 } 299 return "" 300 } 301 302 func getConfigOrEnv(config string, env ...string) string { 303 if config != "" { 304 return config 305 } 306 return getEnvAny(env...) 307 }