info.go 9.3 KB

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