2018-02-05 16:05:59 -05:00
package daemon // import "github.com/docker/docker/daemon"
2014-08-07 23:01:55 -04:00
import (
2016-11-16 16:30:29 -05:00
"fmt"
2018-09-26 22:43:26 -04:00
"net/url"
2014-08-07 23:01:55 -04:00
"os"
"runtime"
2017-05-16 19:56:56 -04:00
"strings"
2015-03-10 14:25:47 -04:00
"time"
2014-08-07 23:01:55 -04:00
2016-11-02 13:04:39 -04:00
"github.com/docker/docker/api"
2016-09-06 14:18:12 -04:00
"github.com/docker/docker/api/types"
2016-12-12 03:33:58 -05:00
"github.com/docker/docker/cli/debug"
2020-07-07 16:33:46 -04:00
"github.com/docker/docker/daemon/config"
2017-04-11 17:21:21 -04:00
"github.com/docker/docker/daemon/logger"
2015-11-09 13:32:46 -05:00
"github.com/docker/docker/dockerversion"
2015-03-29 17:17:23 -04:00
"github.com/docker/docker/pkg/fileutils"
2014-08-07 23:01:55 -04:00
"github.com/docker/docker/pkg/parsers/kernel"
"github.com/docker/docker/pkg/parsers/operatingsystem"
2015-11-14 17:03:02 -05:00
"github.com/docker/docker/pkg/platform"
2015-08-06 07:54:48 -04:00
"github.com/docker/docker/pkg/sysinfo"
2014-10-24 18:48:23 -04:00
"github.com/docker/docker/pkg/system"
2014-08-07 23:01:55 -04:00
"github.com/docker/docker/registry"
2019-08-05 10:37:47 -04:00
metrics "github.com/docker/go-metrics"
2020-12-14 05:46:58 -05:00
"github.com/opencontainers/selinux/go-selinux"
2017-07-26 17:42:13 -04:00
"github.com/sirupsen/logrus"
2014-08-07 23:01:55 -04:00
)
2015-07-30 17:01:53 -04:00
// SystemInfo returns information about the host server the daemon is running on.
2019-08-28 19:44:39 -04:00
func ( daemon * Daemon ) SystemInfo ( ) * types . Info {
2019-05-30 12:51:41 -04:00
defer metrics . StartTimer ( hostInfoFunctions . WithValues ( "system_info" ) ) ( )
2020-03-10 08:09:25 -04:00
sysInfo := daemon . RawSysInfo ( true )
2017-02-09 21:57:35 -05:00
cRunning , cPaused , cStopped := stateCtr . get ( )
2015-10-27 16:12:33 -04:00
2016-11-16 16:30:29 -05:00
v := & types . Info {
2015-04-10 13:26:30 -04:00
ID : daemon . ID ,
2017-08-24 13:11:44 -04:00
Containers : cRunning + cPaused + cStopped ,
ContainersRunning : cRunning ,
ContainersPaused : cPaused ,
ContainersStopped : cStopped ,
2018-02-02 17:18:46 -05:00
Images : daemon . imageService . CountImages ( ) ,
2015-08-06 07:54:48 -04:00
IPv4Forwarding : ! sysInfo . IPv4ForwardingDisabled ,
2016-02-26 13:47:43 -05:00
BridgeNfIptables : ! sysInfo . BridgeNFCallIPTablesDisabled ,
BridgeNfIP6tables : ! sysInfo . BridgeNFCallIP6TablesDisabled ,
2016-12-12 03:33:58 -05:00
Debug : debug . IsEnabled ( ) ,
2018-07-13 06:55:59 -04:00
Name : hostName ( ) ,
2015-04-10 13:26:30 -04:00
NFd : fileutils . GetTotalUsedFds ( ) ,
NGoroutines : runtime . NumGoroutine ( ) ,
SystemTime : time . Now ( ) . Format ( time . RFC3339Nano ) ,
LoggingDriver : daemon . defaultLogConfig . Type ,
NEventsListener : daemon . EventsService . SubscribersCount ( ) ,
2018-07-13 06:55:59 -04:00
KernelVersion : kernelVersion ( ) ,
OperatingSystem : operatingSystem ( ) ,
2019-05-30 12:51:41 -04:00
OSVersion : osVersion ( ) ,
2015-07-21 15:40:36 -04:00
IndexServerAddress : registry . IndexServer ,
2015-11-14 17:03:02 -05:00
OSType : platform . OSType ,
Architecture : platform . Architecture ,
2016-03-08 16:03:37 -05:00
RegistryConfig : daemon . RegistryService . ServiceConfig ( ) ,
2016-06-25 10:26:00 -04:00
NCPU : sysinfo . NumCPU ( ) ,
2018-07-13 06:55:59 -04:00
MemTotal : memInfo ( ) . MemTotal ,
2017-05-30 20:02:11 -04:00
GenericResources : daemon . genericResources ,
2015-12-03 05:46:53 -05:00
DockerRootDir : daemon . configStore . Root ,
Labels : daemon . configStore . Labels ,
2016-10-06 10:09:54 -04:00
ExperimentalBuild : daemon . configStore . Experimental ,
2015-11-09 13:32:46 -05:00
ServerVersion : dockerversion . Version ,
2019-09-25 04:56:41 -04:00
HTTPProxy : maskCredentials ( getEnvAny ( "HTTP_PROXY" , "http_proxy" ) ) ,
HTTPSProxy : maskCredentials ( getEnvAny ( "HTTPS_PROXY" , "https_proxy" ) ) ,
NoProxy : getEnvAny ( "NO_PROXY" , "no_proxy" ) ,
2016-07-24 16:00:15 -04:00
LiveRestoreEnabled : daemon . configStore . LiveRestoreEnabled ,
2016-09-07 18:10:00 -04:00
Isolation : daemon . defaultIsolation ,
2015-04-10 13:26:30 -04:00
}
2020-03-03 11:27:48 -05:00
daemon . fillClusterInfo ( v )
2018-08-21 08:06:06 -04:00
daemon . fillAPIInfo ( v )
2016-11-11 11:02:23 -05:00
// Retrieve platform specific info
2018-07-13 07:14:45 -04:00
daemon . fillPlatformInfo ( v , sysInfo )
2018-07-13 06:55:59 -04:00
daemon . fillDriverInfo ( v )
daemon . fillPluginsInfo ( v )
daemon . fillSecurityOptions ( v , sysInfo )
2018-08-17 20:05:21 -04:00
daemon . fillLicense ( v )
2020-07-06 23:17:51 -04:00
daemon . fillDefaultAddressPools ( v )
2015-04-10 13:26:30 -04:00
2020-07-07 16:33:46 -04:00
if v . DefaultRuntime == config . LinuxV1RuntimeName {
v . Warnings = append ( v . Warnings , fmt . Sprintf ( "Configured default runtime %q is deprecated and will be removed in the next release." , config . LinuxV1RuntimeName ) )
}
2019-08-28 19:44:39 -04:00
return v
2014-08-07 23:01:55 -04:00
}
2015-10-23 02:08:26 -04:00
2015-12-03 13:11:19 -05:00
// SystemVersion returns version information about the daemon.
func ( daemon * Daemon ) SystemVersion ( ) types . Version {
2019-05-30 12:51:41 -04:00
defer metrics . StartTimer ( hostInfoFunctions . WithValues ( "system_version" ) ) ( )
2018-07-13 06:55:59 -04:00
kernelVersion := kernelVersion ( )
2017-12-05 09:29:37 -05:00
2015-12-03 13:11:19 -05:00
v := types . Version {
2017-12-05 09:29:37 -05:00
Components : [ ] types . ComponentVersion {
{
Name : "Engine" ,
Version : dockerversion . Version ,
Details : map [ string ] string {
"GitCommit" : dockerversion . GitCommit ,
"ApiVersion" : api . DefaultVersion ,
"MinAPIVersion" : api . MinVersion ,
"GoVersion" : runtime . Version ( ) ,
"Os" : runtime . GOOS ,
"Arch" : runtime . GOARCH ,
"BuildTime" : dockerversion . BuildTime ,
"KernelVersion" : kernelVersion ,
"Experimental" : fmt . Sprintf ( "%t" , daemon . configStore . Experimental ) ,
} ,
} ,
} ,
// Populate deprecated fields for older clients
2016-11-02 13:04:39 -04:00
Version : dockerversion . Version ,
GitCommit : dockerversion . GitCommit ,
2017-12-05 09:29:37 -05:00
APIVersion : api . DefaultVersion ,
2016-11-02 13:04:39 -04:00
MinAPIVersion : api . MinVersion ,
GoVersion : runtime . Version ( ) ,
Os : runtime . GOOS ,
Arch : runtime . GOARCH ,
BuildTime : dockerversion . BuildTime ,
2017-12-05 09:29:37 -05:00
KernelVersion : kernelVersion ,
2016-11-02 13:04:39 -04:00
Experimental : daemon . configStore . Experimental ,
2015-12-03 13:11:19 -05:00
}
2017-12-05 09:29:37 -05:00
v . Platform . Name = dockerversion . PlatformName
2015-12-03 13:11:19 -05:00
Add containerd, runc, and docker-init versions to /version
This patch adds version information about the containerd,
runc, and docker-init components to the /version endpoint.
With this patch applied, running:
```
curl --unix-socket /var/run/docker.sock http://localhost/version | jq .
```
Will produce this response:
```json
{
"Platform": {
"Name": ""
},
"Components": [
{
"Name": "Engine",
"Version": "dev",
"Details": {
"ApiVersion": "1.40",
"Arch": "amd64",
"BuildTime": "2018-11-08T10:23:42.000000000+00:00",
"Experimental": "false",
"GitCommit": "7d02782d2f",
"GoVersion": "go1.11.2",
"KernelVersion": "4.9.93-linuxkit-aufs",
"MinAPIVersion": "1.12",
"Os": "linux"
}
},
{
"Name": "containerd",
"Version": "v1.1.4",
"Details": {
"GitCommit": "9f2e07b1fc1342d1c48fe4d7bbb94cb6d1bf278b"
}
},
{
"Name": "runc",
"Version": "1.0.0-rc5+dev",
"Details": {
"GitCommit": "a00bf0190895aa465a5fbed0268888e2c8ddfe85"
}
},
{
"Name": "docker-init",
"Version": "0.18.0",
"Details": {
"GitCommit": "fec3683"
}
}
],
"Version": "dev",
"ApiVersion": "1.40",
"MinAPIVersion": "1.12",
"GitCommit": "7d02782d2f",
"GoVersion": "go1.11.2",
"Os": "linux",
"Arch": "amd64",
"KernelVersion": "4.9.93-linuxkit-aufs",
"BuildTime": "2018-11-08T10:23:42.000000000+00:00"
}
```
When using a recent version of the CLI, that information is included in the
output of `docker version`:
```
Client: Docker Engine - Community
Version: 18.09.0
API version: 1.39
Go version: go1.10.4
Git commit: 4d60db4
Built: Wed Nov 7 00:46:51 2018
OS/Arch: linux/amd64
Experimental: false
Server:
Engine:
Version: dev
API version: 1.40 (minimum version 1.12)
Go version: go1.11.2
Git commit: 7d02782d2f
Built: Thu Nov 8 10:23:42 2018
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: v1.1.4
GitCommit: 9f2e07b1fc1342d1c48fe4d7bbb94cb6d1bf278b
runc:
Version: 1.0.0-rc5+dev
GitCommit: a00bf0190895aa465a5fbed0268888e2c8ddfe85
docker-init:
Version: 0.18.0
GitCommit: fec3683
```
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-10-05 06:30:10 -04:00
daemon . fillPlatformVersion ( & v )
2015-12-03 13:11:19 -05:00
return v
}
2020-03-03 11:27:48 -05:00
func ( daemon * Daemon ) fillClusterInfo ( v * types . Info ) {
v . ClusterAdvertise = daemon . configStore . ClusterAdvertise
v . ClusterStore = daemon . configStore . ClusterStore
if v . ClusterAdvertise != "" || v . ClusterStore != "" {
v . Warnings = append ( v . Warnings , ` WARNING : node discovery and overlay networks with an external k / v store ( cluster - advertise ,
cluster - store , cluster - store - opt ) are deprecated and will be removed in a future release . ` )
}
}
2018-07-13 06:55:59 -04:00
func ( daemon * Daemon ) fillDriverInfo ( v * types . Info ) {
var ds [ ] [ 2 ] string
drivers := ""
statuses := daemon . imageService . LayerStoreStatus ( )
for os , gd := range daemon . graphDrivers {
ds = append ( ds , statuses [ os ] ... )
drivers += gd
if len ( daemon . graphDrivers ) > 1 {
drivers += fmt . Sprintf ( " (%s) " , os )
}
2018-10-11 06:44:43 -04:00
switch gd {
2018-10-26 12:41:46 -04:00
case "aufs" , "devicemapper" , "overlay" :
2018-10-11 06:44:43 -04:00
v . Warnings = append ( v . Warnings , fmt . Sprintf ( "WARNING: the %s storage-driver is deprecated, and will be removed in a future release." , gd ) )
}
2018-07-13 06:55:59 -04:00
}
drivers = strings . TrimSpace ( drivers )
2015-10-23 02:08:26 -04:00
2018-07-13 06:55:59 -04:00
v . Driver = drivers
v . DriverStatus = ds
2018-07-19 07:45:32 -04:00
fillDriverWarnings ( v )
2018-07-13 06:55:59 -04:00
}
2015-12-29 16:10:23 -05:00
2018-07-13 06:55:59 -04:00
func ( daemon * Daemon ) fillPluginsInfo ( v * types . Info ) {
v . Plugins = types . PluginsInfo {
Volume : daemon . volumes . GetDriverList ( ) ,
Network : daemon . GetNetworkDriverList ( ) ,
// The authorization plugins are returned in the order they are
// used as they constitute a request/response modification chain.
Authorization : daemon . configStore . AuthorizationPlugins ,
Log : logger . ListDrivers ( ) ,
}
}
func ( daemon * Daemon ) fillSecurityOptions ( v * types . Info , sysInfo * sysinfo . SysInfo ) {
var securityOptions [ ] string
if sysInfo . AppArmor {
securityOptions = append ( securityOptions , "name=apparmor" )
}
if sysInfo . Seccomp && supportsSeccomp {
profile := daemon . seccompProfilePath
if profile == "" {
profile = "default"
}
securityOptions = append ( securityOptions , fmt . Sprintf ( "name=seccomp,profile=%s" , profile ) )
}
2020-12-14 05:46:58 -05:00
if selinux . GetEnabled ( ) {
2018-07-13 06:55:59 -04:00
securityOptions = append ( securityOptions , "name=selinux" )
}
2017-11-16 01:20:33 -05:00
if rootIDs := daemon . idMapping . RootPair ( ) ; rootIDs . UID != 0 || rootIDs . GID != 0 {
2018-07-13 06:55:59 -04:00
securityOptions = append ( securityOptions , "name=userns" )
}
2019-02-28 03:12:55 -05:00
if daemon . Rootless ( ) {
2018-10-15 03:52:53 -04:00
securityOptions = append ( securityOptions , "name=rootless" )
}
2019-03-14 23:44:18 -04:00
if daemon . cgroupNamespacesEnabled ( sysInfo ) {
securityOptions = append ( securityOptions , "name=cgroupns" )
}
2018-07-13 06:55:59 -04:00
v . SecurityOptions = securityOptions
}
2018-08-21 08:06:06 -04:00
func ( daemon * Daemon ) fillAPIInfo ( v * types . Info ) {
const warn string = `
Access to the remote API is equivalent to root access on the host . Refer
to the ' Docker daemon attack surface ' section in the documentation for
2021-02-25 06:11:50 -05:00
more information : https : //docs.docker.com/go/attack-surface/`
2018-08-21 08:06:06 -04:00
cfg := daemon . configStore
for _ , host := range cfg . Hosts {
// cnf.Hosts is normalized during startup, so should always have a scheme/proto
h := strings . SplitN ( host , "://" , 2 )
proto := h [ 0 ]
addr := h [ 1 ]
if proto != "tcp" {
continue
}
2020-07-28 19:01:08 -04:00
if cfg . TLS == nil || ! * cfg . TLS {
2018-08-21 08:06:06 -04:00
v . Warnings = append ( v . Warnings , fmt . Sprintf ( "WARNING: API is accessible on http://%s without encryption.%s" , addr , warn ) )
continue
}
2020-07-28 19:01:08 -04:00
if cfg . TLSVerify == nil || ! * cfg . TLSVerify {
2018-08-21 08:06:06 -04:00
v . Warnings = append ( v . Warnings , fmt . Sprintf ( "WARNING: API is accessible on https://%s without TLS client verification.%s" , addr , warn ) )
continue
}
}
}
2020-07-06 23:17:51 -04:00
func ( daemon * Daemon ) fillDefaultAddressPools ( v * types . Info ) {
for _ , pool := range daemon . configStore . DefaultAddressPools . Value ( ) {
v . DefaultAddressPools = append ( v . DefaultAddressPools , types . NetworkAddressPool {
Base : pool . Base ,
Size : pool . Size ,
} )
}
}
2018-07-13 06:55:59 -04:00
func hostName ( ) string {
hostname := ""
if hn , err := os . Hostname ( ) ; err != nil {
logrus . Warnf ( "Could not get hostname: %v" , err )
} else {
hostname = hn
}
return hostname
}
func kernelVersion ( ) string {
2018-07-16 10:07:47 -04:00
var kernelVersion string
2018-07-13 06:55:59 -04:00
if kv , err := kernel . GetKernelVersion ( ) ; err != nil {
logrus . Warnf ( "Could not get kernel version: %v" , err )
} else {
kernelVersion = kv . String ( )
}
return kernelVersion
}
func memInfo ( ) * system . MemInfo {
memInfo , err := system . ReadMemInfo ( )
if err != nil {
logrus . Errorf ( "Could not read system memory info: %v" , err )
memInfo = & system . MemInfo { }
}
return memInfo
}
2019-05-30 12:51:41 -04:00
func operatingSystem ( ) ( operatingSystem string ) {
defer metrics . StartTimer ( hostInfoFunctions . WithValues ( "operating_system" ) ) ( )
2018-07-13 06:55:59 -04:00
if s , err := operatingsystem . GetOperatingSystem ( ) ; err != nil {
logrus . Warnf ( "Could not get operating system name: %v" , err )
} else {
operatingSystem = s
}
// Don't do containerized check on Windows
if runtime . GOOS != "windows" {
if inContainer , err := operatingsystem . IsContainerized ( ) ; err != nil {
logrus . Errorf ( "Could not determine if daemon is containerized: %v" , err )
operatingSystem += " (error determining if containerized)"
} else if inContainer {
operatingSystem += " (containerized)"
}
}
2019-05-30 12:51:41 -04:00
2018-07-13 06:55:59 -04:00
return operatingSystem
2015-10-23 02:08:26 -04:00
}
2018-09-26 22:43:26 -04:00
2019-05-30 12:51:41 -04:00
func osVersion ( ) ( version string ) {
defer metrics . StartTimer ( hostInfoFunctions . WithValues ( "os_version" ) ) ( )
version , err := operatingsystem . GetOperatingSystemVersion ( )
if err != nil {
logrus . Warnf ( "Could not get operating system version: %v" , err )
}
return version
}
2018-09-26 22:43:26 -04:00
func maskCredentials ( rawURL string ) string {
parsedURL , err := url . Parse ( rawURL )
if err != nil || parsedURL . User == nil {
return rawURL
}
parsedURL . User = url . UserPassword ( "xxxxx" , "xxxxx" )
maskedURL := parsedURL . String ( )
return maskedURL
}
2019-09-25 04:56:41 -04:00
func getEnvAny ( names ... string ) string {
for _ , n := range names {
if val := os . Getenv ( n ) ; val != "" {
return val
}
}
return ""
}