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"
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" ) ) ( )
2021-07-14 10:45:02 -04:00
sysInfo := daemon . RawSysInfo ( )
2015-10-27 16:12:33 -04:00
2016-11-16 16:30:29 -05:00
v := & types . Info {
2022-03-02 05:43:33 -05:00
ID : daemon . id ,
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 ,
2018-07-13 06:55:59 -04:00
Name : hostName ( ) ,
2015-04-10 13:26:30 -04:00
SystemTime : time . Now ( ) . Format ( time . RFC3339Nano ) ,
LoggingDriver : daemon . defaultLogConfig . Type ,
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 ,
2022-03-02 05:43:33 -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 ,
2021-07-16 03:33:00 -04:00
HTTPProxy : config . MaskCredentials ( getConfigOrEnv ( daemon . configStore . HTTPProxy , "HTTP_PROXY" , "http_proxy" ) ) ,
HTTPSProxy : config . MaskCredentials ( getConfigOrEnv ( daemon . configStore . HTTPSProxy , "HTTPS_PROXY" , "https_proxy" ) ) ,
NoProxy : getConfigOrEnv ( daemon . configStore . NoProxy , "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
}
2022-02-15 13:19:30 -05:00
daemon . fillContainerStates ( v )
2022-03-02 06:52:29 -05:00
daemon . fillDebugInfo ( 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
}
2018-07-13 06:55:59 -04:00
func ( daemon * Daemon ) fillDriverInfo ( v * types . Info ) {
daemon: require storage-driver to be set if the driver is deprecated
Previously, we only printed a warning if a storage driver was deprecated. The
intent was to continue supporting these drivers, to allow users to migrate
to a different storage driver.
This patch changes the behavior; if the user has no storage driver specified
in the daemon configuration (so if we try to detect the previous storage
driver based on what's present in /var/lib/docker), we now produce an error,
informing the user that the storage driver is deprecated (and to be removed),
as well as instructing them to change the daemon configuration to explicitly
select the storage driver (to allow them to migrate).
This should make the deprecation more visible; this will be disruptive, but
it's better to have the failure happening *now* (while the drivers are still
there), than for users to discover the storage driver is no longer there
(which would require them to *downgrade* the daemon in order to migrate
to a different driver).
With this change, `docker info` includes a link in the warnings that:
/ # docker info
Client:
Context: default
Debug Mode: false
Server:
...
Live Restore Enabled: false
WARNING: The overlay storage-driver is deprecated, and will be removed in a future release.
Refer to the documentation for more information: https://docs.docker.com/go/storage-driver/
When starting the daemon without a storage driver configured explicitly, but
previous state was using a deprecated driver, the error is both logged and
printed:
...
ERRO[2022-03-25T14:14:06.032014013Z] [graphdriver] prior storage driver overlay is deprecated and will be removed in a future release; update the the daemon configuration and explicitly choose this storage driver to continue using it; visit https://docs.docker.com/go/storage-driver/ for more information
...
failed to start daemon: error initializing graphdriver: prior storage driver overlay is deprecated and will be removed in a future release; update the the daemon configuration and explicitly choose this storage driver to continue using it; visit https://docs.docker.com/go/storage-driver/ for more information
When starting the daemon and explicitly configuring it with a deprecated storage
driver:
WARN[2022-03-25T14:15:59.042335412Z] [graphdriver] WARNING: the overlay storage-driver is deprecated and will be removed in a future release; visit https://docs.docker.com/go/storage-driver/ for more information
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-03-11 11:51:12 -05:00
const warnMsg = `
WARNING : The % s storage - driver is deprecated , and will be removed in a future release .
Refer to the documentation for more information : https : //docs.docker.com/go/storage-driver/`
2021-06-10 04:06:04 -04:00
switch daemon . graphDriver {
case "aufs" , "devicemapper" , "overlay" :
daemon: require storage-driver to be set if the driver is deprecated
Previously, we only printed a warning if a storage driver was deprecated. The
intent was to continue supporting these drivers, to allow users to migrate
to a different storage driver.
This patch changes the behavior; if the user has no storage driver specified
in the daemon configuration (so if we try to detect the previous storage
driver based on what's present in /var/lib/docker), we now produce an error,
informing the user that the storage driver is deprecated (and to be removed),
as well as instructing them to change the daemon configuration to explicitly
select the storage driver (to allow them to migrate).
This should make the deprecation more visible; this will be disruptive, but
it's better to have the failure happening *now* (while the drivers are still
there), than for users to discover the storage driver is no longer there
(which would require them to *downgrade* the daemon in order to migrate
to a different driver).
With this change, `docker info` includes a link in the warnings that:
/ # docker info
Client:
Context: default
Debug Mode: false
Server:
...
Live Restore Enabled: false
WARNING: The overlay storage-driver is deprecated, and will be removed in a future release.
Refer to the documentation for more information: https://docs.docker.com/go/storage-driver/
When starting the daemon without a storage driver configured explicitly, but
previous state was using a deprecated driver, the error is both logged and
printed:
...
ERRO[2022-03-25T14:14:06.032014013Z] [graphdriver] prior storage driver overlay is deprecated and will be removed in a future release; update the the daemon configuration and explicitly choose this storage driver to continue using it; visit https://docs.docker.com/go/storage-driver/ for more information
...
failed to start daemon: error initializing graphdriver: prior storage driver overlay is deprecated and will be removed in a future release; update the the daemon configuration and explicitly choose this storage driver to continue using it; visit https://docs.docker.com/go/storage-driver/ for more information
When starting the daemon and explicitly configuring it with a deprecated storage
driver:
WARN[2022-03-25T14:15:59.042335412Z] [graphdriver] WARNING: the overlay storage-driver is deprecated and will be removed in a future release; visit https://docs.docker.com/go/storage-driver/ for more information
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-03-11 11:51:12 -05:00
v . Warnings = append ( v . Warnings , fmt . Sprintf ( warnMsg , daemon . graphDriver ) )
2018-07-13 06:55:59 -04:00
}
2015-10-23 02:08:26 -04:00
2021-06-10 04:06:04 -04:00
v . Driver = daemon . graphDriver
2021-03-19 10:34:08 -04:00
v . DriverStatus = daemon . imageService . LayerStoreStatus ( )
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 {
2021-07-07 07:09:54 -04:00
if daemon . seccompProfilePath != config . SeccompProfileDefault {
2021-06-07 12:41:21 -04:00
v . Warnings = append ( v . Warnings , "WARNING: daemon is not using the default seccomp profile" )
}
2021-07-07 07:09:54 -04:00
securityOptions = append ( securityOptions , "name=seccomp,profile=" + daemon . seccompProfilePath )
2018-07-13 06:55:59 -04:00
}
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
}
2022-02-15 13:19:30 -05:00
func ( daemon * Daemon ) fillContainerStates ( v * types . Info ) {
cRunning , cPaused , cStopped := stateCtr . get ( )
v . Containers = cRunning + cPaused + cStopped
v . ContainersPaused = cPaused
v . ContainersRunning = cRunning
v . ContainersStopped = cStopped
}
2022-03-02 06:52:29 -05:00
// fillDebugInfo sets the current debugging state of the daemon, and additional
// debugging information, such as the number of Go-routines, and file descriptors.
//
// Note that this currently always collects the information, but the CLI only
// prints it if the daemon has debug enabled. We should consider to either make
// this information optional (cli to request "with debugging information"), or
// only collect it if the daemon has debug enabled. For the CLI code, see
// https://github.com/docker/cli/blob/v20.10.12/cli/command/system/info.go#L239-L244
func ( daemon * Daemon ) fillDebugInfo ( v * types . Info ) {
v . Debug = debug . IsEnabled ( )
v . NFd = fileutils . GetTotalUsedFds ( )
v . NGoroutines = runtime . NumGoroutine ( )
v . NEventsListener = daemon . EventsService . SubscribersCount ( )
}
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
}
2022-02-17 12:25:38 -05:00
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)"
2018-07-13 06:55:59 -04:00
}
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
}
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 ""
}
2021-07-16 03:33:00 -04:00
func getConfigOrEnv ( config string , env ... string ) string {
if config != "" {
return config
}
return getEnvAny ( env ... )
}