info.go 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. package daemon // import "github.com/docker/docker/daemon"
  2. import (
  3. "fmt"
  4. "net/url"
  5. "os"
  6. "runtime"
  7. "strings"
  8. "time"
  9. "github.com/docker/docker/api"
  10. "github.com/docker/docker/api/types"
  11. "github.com/docker/docker/cli/debug"
  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/sirupsen/logrus"
  23. )
  24. // SystemInfo returns information about the host server the daemon is running on.
  25. func (daemon *Daemon) SystemInfo() (*types.Info, error) {
  26. defer metrics.StartTimer(hostInfoFunctions.WithValues("system_info"))()
  27. sysInfo := sysinfo.New(true)
  28. cRunning, cPaused, cStopped := stateCtr.get()
  29. v := &types.Info{
  30. ID: daemon.ID,
  31. Containers: cRunning + cPaused + cStopped,
  32. ContainersRunning: cRunning,
  33. ContainersPaused: cPaused,
  34. ContainersStopped: cStopped,
  35. Images: daemon.imageService.CountImages(),
  36. IPv4Forwarding: !sysInfo.IPv4ForwardingDisabled,
  37. BridgeNfIptables: !sysInfo.BridgeNFCallIPTablesDisabled,
  38. BridgeNfIP6tables: !sysInfo.BridgeNFCallIP6TablesDisabled,
  39. Debug: debug.IsEnabled(),
  40. Name: hostName(),
  41. NFd: fileutils.GetTotalUsedFds(),
  42. NGoroutines: runtime.NumGoroutine(),
  43. SystemTime: time.Now().Format(time.RFC3339Nano),
  44. LoggingDriver: daemon.defaultLogConfig.Type,
  45. CgroupDriver: daemon.getCgroupDriver(),
  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. ClusterStore: daemon.configStore.ClusterStore,
  62. ClusterAdvertise: daemon.configStore.ClusterAdvertise,
  63. HTTPProxy: maskCredentials(getEnvAny("HTTP_PROXY", "http_proxy")),
  64. HTTPSProxy: maskCredentials(getEnvAny("HTTPS_PROXY", "https_proxy")),
  65. NoProxy: getEnvAny("NO_PROXY", "no_proxy"),
  66. LiveRestoreEnabled: daemon.configStore.LiveRestoreEnabled,
  67. Isolation: daemon.defaultIsolation,
  68. }
  69. daemon.fillAPIInfo(v)
  70. // Retrieve platform specific info
  71. daemon.fillPlatformInfo(v, sysInfo)
  72. daemon.fillDriverInfo(v)
  73. daemon.fillPluginsInfo(v)
  74. daemon.fillSecurityOptions(v, sysInfo)
  75. daemon.fillLicense(v)
  76. return v, nil
  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. kernelVersion := kernelVersion()
  82. v := types.Version{
  83. Components: []types.ComponentVersion{
  84. {
  85. Name: "Engine",
  86. Version: dockerversion.Version,
  87. Details: map[string]string{
  88. "GitCommit": dockerversion.GitCommit,
  89. "ApiVersion": api.DefaultVersion,
  90. "MinAPIVersion": api.MinVersion,
  91. "GoVersion": runtime.Version(),
  92. "Os": runtime.GOOS,
  93. "Arch": runtime.GOARCH,
  94. "BuildTime": dockerversion.BuildTime,
  95. "KernelVersion": kernelVersion,
  96. "Experimental": fmt.Sprintf("%t", daemon.configStore.Experimental),
  97. },
  98. },
  99. },
  100. // Populate deprecated fields for older clients
  101. Version: dockerversion.Version,
  102. GitCommit: dockerversion.GitCommit,
  103. APIVersion: api.DefaultVersion,
  104. MinAPIVersion: api.MinVersion,
  105. GoVersion: runtime.Version(),
  106. Os: runtime.GOOS,
  107. Arch: runtime.GOARCH,
  108. BuildTime: dockerversion.BuildTime,
  109. KernelVersion: kernelVersion,
  110. Experimental: daemon.configStore.Experimental,
  111. }
  112. v.Platform.Name = dockerversion.PlatformName
  113. daemon.fillPlatformVersion(&v)
  114. return v
  115. }
  116. func (daemon *Daemon) fillDriverInfo(v *types.Info) {
  117. var ds [][2]string
  118. drivers := ""
  119. statuses := daemon.imageService.LayerStoreStatus()
  120. for os, gd := range daemon.graphDrivers {
  121. ds = append(ds, statuses[os]...)
  122. drivers += gd
  123. if len(daemon.graphDrivers) > 1 {
  124. drivers += fmt.Sprintf(" (%s) ", os)
  125. }
  126. switch gd {
  127. case "aufs", "devicemapper", "overlay":
  128. v.Warnings = append(v.Warnings, fmt.Sprintf("WARNING: the %s storage-driver is deprecated, and will be removed in a future release.", gd))
  129. }
  130. }
  131. drivers = strings.TrimSpace(drivers)
  132. v.Driver = drivers
  133. v.DriverStatus = ds
  134. fillDriverWarnings(v)
  135. }
  136. func (daemon *Daemon) fillPluginsInfo(v *types.Info) {
  137. v.Plugins = types.PluginsInfo{
  138. Volume: daemon.volumes.GetDriverList(),
  139. Network: daemon.GetNetworkDriverList(),
  140. // The authorization plugins are returned in the order they are
  141. // used as they constitute a request/response modification chain.
  142. Authorization: daemon.configStore.AuthorizationPlugins,
  143. Log: logger.ListDrivers(),
  144. }
  145. }
  146. func (daemon *Daemon) fillSecurityOptions(v *types.Info, sysInfo *sysinfo.SysInfo) {
  147. var securityOptions []string
  148. if sysInfo.AppArmor {
  149. securityOptions = append(securityOptions, "name=apparmor")
  150. }
  151. if sysInfo.Seccomp && supportsSeccomp {
  152. profile := daemon.seccompProfilePath
  153. if profile == "" {
  154. profile = "default"
  155. }
  156. securityOptions = append(securityOptions, fmt.Sprintf("name=seccomp,profile=%s", profile))
  157. }
  158. if selinuxEnabled() {
  159. securityOptions = append(securityOptions, "name=selinux")
  160. }
  161. if rootIDs := daemon.idMapping.RootPair(); rootIDs.UID != 0 || rootIDs.GID != 0 {
  162. securityOptions = append(securityOptions, "name=userns")
  163. }
  164. if daemon.Rootless() {
  165. securityOptions = append(securityOptions, "name=rootless")
  166. }
  167. if daemon.cgroupNamespacesEnabled(sysInfo) {
  168. securityOptions = append(securityOptions, "name=cgroupns")
  169. }
  170. v.SecurityOptions = securityOptions
  171. }
  172. func (daemon *Daemon) fillAPIInfo(v *types.Info) {
  173. const warn string = `
  174. Access to the remote API is equivalent to root access on the host. Refer
  175. to the 'Docker daemon attack surface' section in the documentation for
  176. more information: https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface`
  177. cfg := daemon.configStore
  178. for _, host := range cfg.Hosts {
  179. // cnf.Hosts is normalized during startup, so should always have a scheme/proto
  180. h := strings.SplitN(host, "://", 2)
  181. proto := h[0]
  182. addr := h[1]
  183. if proto != "tcp" {
  184. continue
  185. }
  186. if !cfg.TLS {
  187. v.Warnings = append(v.Warnings, fmt.Sprintf("WARNING: API is accessible on http://%s without encryption.%s", addr, warn))
  188. continue
  189. }
  190. if !cfg.TLSVerify {
  191. v.Warnings = append(v.Warnings, fmt.Sprintf("WARNING: API is accessible on https://%s without TLS client verification.%s", addr, warn))
  192. continue
  193. }
  194. }
  195. }
  196. func hostName() string {
  197. hostname := ""
  198. if hn, err := os.Hostname(); err != nil {
  199. logrus.Warnf("Could not get hostname: %v", err)
  200. } else {
  201. hostname = hn
  202. }
  203. return hostname
  204. }
  205. func kernelVersion() string {
  206. var kernelVersion string
  207. if kv, err := kernel.GetKernelVersion(); err != nil {
  208. logrus.Warnf("Could not get kernel version: %v", err)
  209. } else {
  210. kernelVersion = kv.String()
  211. }
  212. return kernelVersion
  213. }
  214. func memInfo() *system.MemInfo {
  215. memInfo, err := system.ReadMemInfo()
  216. if err != nil {
  217. logrus.Errorf("Could not read system memory info: %v", err)
  218. memInfo = &system.MemInfo{}
  219. }
  220. return memInfo
  221. }
  222. func operatingSystem() (operatingSystem string) {
  223. defer metrics.StartTimer(hostInfoFunctions.WithValues("operating_system"))()
  224. if s, err := operatingsystem.GetOperatingSystem(); err != nil {
  225. logrus.Warnf("Could not get operating system name: %v", err)
  226. } else {
  227. operatingSystem = s
  228. }
  229. // Don't do containerized check on Windows
  230. if runtime.GOOS != "windows" {
  231. if inContainer, err := operatingsystem.IsContainerized(); err != nil {
  232. logrus.Errorf("Could not determine if daemon is containerized: %v", err)
  233. operatingSystem += " (error determining if containerized)"
  234. } else if inContainer {
  235. operatingSystem += " (containerized)"
  236. }
  237. }
  238. return operatingSystem
  239. }
  240. func osVersion() (version string) {
  241. defer metrics.StartTimer(hostInfoFunctions.WithValues("os_version"))()
  242. version, err := operatingsystem.GetOperatingSystemVersion()
  243. if err != nil {
  244. logrus.Warnf("Could not get operating system version: %v", err)
  245. }
  246. return version
  247. }
  248. func maskCredentials(rawURL string) string {
  249. parsedURL, err := url.Parse(rawURL)
  250. if err != nil || parsedURL.User == nil {
  251. return rawURL
  252. }
  253. parsedURL.User = url.UserPassword("xxxxx", "xxxxx")
  254. maskedURL := parsedURL.String()
  255. return maskedURL
  256. }
  257. func getEnvAny(names ...string) string {
  258. for _, n := range names {
  259. if val := os.Getenv(n); val != "" {
  260. return val
  261. }
  262. }
  263. return ""
  264. }