2015-03-24 23:57:23 -04:00
package client
import (
"fmt"
2015-12-29 16:10:23 -05:00
"strings"
2015-03-24 23:57:23 -04:00
2016-03-16 15:19:22 -04:00
"golang.org/x/net/context"
2015-05-05 00:18:28 -04:00
Cli "github.com/docker/docker/cli"
2015-05-29 19:48:02 -04:00
"github.com/docker/docker/pkg/ioutils"
2015-03-24 23:57:23 -04:00
flag "github.com/docker/docker/pkg/mflag"
2016-02-01 18:09:25 -05:00
"github.com/docker/docker/utils"
2015-12-16 12:26:49 -05:00
"github.com/docker/go-units"
2015-03-24 23:57:23 -04:00
)
2015-03-25 13:34:41 -04:00
// CmdInfo displays system-wide information.
//
// Usage: docker info
2015-03-24 23:57:23 -04:00
func ( cli * DockerCli ) CmdInfo ( args ... string ) error {
2015-10-08 08:46:21 -04:00
cmd := Cli . Subcmd ( "info" , nil , Cli . DockerCommands [ "info" ] . Description , true )
2015-03-24 23:57:23 -04:00
cmd . Require ( flag . Exact , 0 )
2015-07-03 05:26:09 -04:00
2015-05-23 11:57:50 -04:00
cmd . ParseFlags ( args , true )
2015-03-24 23:57:23 -04:00
2016-03-16 15:19:22 -04:00
info , err := cli . client . Info ( context . Background ( ) )
2015-03-24 23:57:23 -04:00
if err != nil {
return err
}
2015-04-10 13:26:30 -04:00
fmt . Fprintf ( cli . out , "Containers: %d\n" , info . Containers )
2015-10-27 16:12:33 -04:00
fmt . Fprintf ( cli . out , " Running: %d\n" , info . ContainersRunning )
fmt . Fprintf ( cli . out , " Paused: %d\n" , info . ContainersPaused )
fmt . Fprintf ( cli . out , " Stopped: %d\n" , info . ContainersStopped )
2015-04-10 13:26:30 -04:00
fmt . Fprintf ( cli . out , "Images: %d\n" , info . Images )
2015-10-14 20:24:13 -04:00
ioutils . FprintfIfNotEmpty ( cli . out , "Server Version: %s\n" , info . ServerVersion )
2015-05-29 19:48:02 -04:00
ioutils . FprintfIfNotEmpty ( cli . out , "Storage Driver: %s\n" , info . Driver )
2015-04-10 13:26:30 -04:00
if info . DriverStatus != nil {
for _ , pair := range info . DriverStatus {
2015-03-24 23:57:23 -04:00
fmt . Fprintf ( cli . out , " %s: %s\n" , pair [ 0 ] , pair [ 1 ] )
2015-12-10 02:58:02 -05:00
// print a warning if devicemapper is using a loopback file
if pair [ 0 ] == "Data loop file" {
2015-12-11 14:23:16 -05:00
fmt . Fprintln ( cli . err , " WARNING: Usage of loopback devices is strongly discouraged for production use. Either use `--storage-opt dm.thinpooldev` or use `--storage-opt dm.no_warn_on_loop_devices=true` to suppress this warning." )
2015-12-10 02:58:02 -05:00
}
2015-03-24 23:57:23 -04:00
}
2015-12-10 02:58:02 -05:00
2015-03-24 23:57:23 -04:00
}
2016-01-24 16:30:21 -05:00
if info . SystemStatus != nil {
for _ , pair := range info . SystemStatus {
fmt . Fprintf ( cli . out , "%s: %s\n" , pair [ 0 ] , pair [ 1 ] )
}
}
2015-05-29 19:48:02 -04:00
ioutils . FprintfIfNotEmpty ( cli . out , "Execution Driver: %s\n" , info . ExecutionDriver )
ioutils . FprintfIfNotEmpty ( cli . out , "Logging Driver: %s\n" , info . LoggingDriver )
2016-02-18 05:10:31 -05:00
ioutils . FprintfIfNotEmpty ( cli . out , "Cgroup Driver: %s\n" , info . CgroupDriver )
2015-10-23 02:08:26 -04:00
fmt . Fprintf ( cli . out , "Plugins: \n" )
fmt . Fprintf ( cli . out , " Volume:" )
2015-12-29 16:10:23 -05:00
fmt . Fprintf ( cli . out , " %s" , strings . Join ( info . Plugins . Volume , " " ) )
2015-10-23 02:08:26 -04:00
fmt . Fprintf ( cli . out , "\n" )
fmt . Fprintf ( cli . out , " Network:" )
2015-12-29 16:10:23 -05:00
fmt . Fprintf ( cli . out , " %s" , strings . Join ( info . Plugins . Network , " " ) )
2015-10-23 02:08:26 -04:00
fmt . Fprintf ( cli . out , "\n" )
2015-12-29 16:10:23 -05:00
if len ( info . Plugins . Authorization ) != 0 {
fmt . Fprintf ( cli . out , " Authorization:" )
fmt . Fprintf ( cli . out , " %s" , strings . Join ( info . Plugins . Authorization , " " ) )
fmt . Fprintf ( cli . out , "\n" )
}
2015-05-29 19:48:02 -04:00
ioutils . FprintfIfNotEmpty ( cli . out , "Kernel Version: %s\n" , info . KernelVersion )
ioutils . FprintfIfNotEmpty ( cli . out , "Operating System: %s\n" , info . OperatingSystem )
2015-06-13 03:39:19 -04:00
ioutils . FprintfIfNotEmpty ( cli . out , "OSType: %s\n" , info . OSType )
ioutils . FprintfIfNotEmpty ( cli . out , "Architecture: %s\n" , info . Architecture )
2015-04-10 13:26:30 -04:00
fmt . Fprintf ( cli . out , "CPUs: %d\n" , info . NCPU )
fmt . Fprintf ( cli . out , "Total Memory: %s\n" , units . BytesSize ( float64 ( info . MemTotal ) ) )
2015-05-29 19:48:02 -04:00
ioutils . FprintfIfNotEmpty ( cli . out , "Name: %s\n" , info . Name )
ioutils . FprintfIfNotEmpty ( cli . out , "ID: %s\n" , info . ID )
2016-02-03 21:10:48 -05:00
fmt . Fprintf ( cli . out , "Docker Root Dir: %s\n" , info . DockerRootDir )
2016-03-28 03:46:53 -04:00
fmt . Fprintf ( cli . out , "Debug Mode (client): %v\n" , utils . IsDebugEnabled ( ) )
fmt . Fprintf ( cli . out , "Debug Mode (server): %v\n" , info . Debug )
2016-02-01 18:09:25 -05:00
2015-03-31 16:49:41 -04:00
if info . Debug {
2015-09-18 22:36:10 -04:00
fmt . Fprintf ( cli . out , " File Descriptors: %d\n" , info . NFd )
fmt . Fprintf ( cli . out , " Goroutines: %d\n" , info . NGoroutines )
fmt . Fprintf ( cli . out , " System Time: %s\n" , info . SystemTime )
fmt . Fprintf ( cli . out , " EventsListeners: %d\n" , info . NEventsListener )
2015-03-24 23:57:23 -04:00
}
2015-04-10 13:26:30 -04:00
2015-07-23 05:40:54 -04:00
ioutils . FprintfIfNotEmpty ( cli . out , "Http Proxy: %s\n" , info . HTTPProxy )
ioutils . FprintfIfNotEmpty ( cli . out , "Https Proxy: %s\n" , info . HTTPSProxy )
2015-05-29 19:48:02 -04:00
ioutils . FprintfIfNotEmpty ( cli . out , "No Proxy: %s\n" , info . NoProxy )
2015-04-10 13:26:30 -04:00
if info . IndexServerAddress != "" {
2015-04-01 18:39:37 -04:00
u := cli . configFile . AuthConfigs [ info . IndexServerAddress ] . Username
2015-03-24 23:57:23 -04:00
if len ( u ) > 0 {
fmt . Fprintf ( cli . out , "Username: %v\n" , u )
}
2016-03-04 15:00:18 -05:00
fmt . Fprintf ( cli . out , "Registry: %v\n" , info . IndexServerAddress )
2015-03-24 23:57:23 -04:00
}
2015-09-18 22:36:10 -04:00
// Only output these warnings if the server does not support these features
2015-12-03 17:20:46 -05:00
if info . OSType != "windows" {
if ! info . MemoryLimit {
2015-12-11 14:23:16 -05:00
fmt . Fprintln ( cli . err , "WARNING: No memory limit support" )
2015-12-03 17:20:46 -05:00
}
if ! info . SwapLimit {
2015-12-11 14:23:16 -05:00
fmt . Fprintln ( cli . err , "WARNING: No swap limit support" )
2015-12-03 17:20:46 -05:00
}
2016-03-02 08:35:17 -05:00
if ! info . KernelMemory {
fmt . Fprintln ( cli . err , "WARNING: No kernel memory limit support" )
}
2015-12-03 17:20:46 -05:00
if ! info . OomKillDisable {
2015-12-11 14:23:16 -05:00
fmt . Fprintln ( cli . err , "WARNING: No oom kill disable support" )
2015-12-03 17:20:46 -05:00
}
if ! info . CPUCfsQuota {
2015-12-11 14:23:16 -05:00
fmt . Fprintln ( cli . err , "WARNING: No cpu cfs quota support" )
2015-12-03 17:20:46 -05:00
}
if ! info . CPUCfsPeriod {
2015-12-11 14:23:16 -05:00
fmt . Fprintln ( cli . err , "WARNING: No cpu cfs period support" )
2015-12-03 17:20:46 -05:00
}
if ! info . CPUShares {
2015-12-11 14:23:16 -05:00
fmt . Fprintln ( cli . err , "WARNING: No cpu shares support" )
2015-12-03 17:20:46 -05:00
}
if ! info . CPUSet {
2015-12-11 14:23:16 -05:00
fmt . Fprintln ( cli . err , "WARNING: No cpuset support" )
2015-12-03 17:20:46 -05:00
}
if ! info . IPv4Forwarding {
2015-12-11 14:23:16 -05:00
fmt . Fprintln ( cli . err , "WARNING: IPv4 forwarding is disabled" )
2015-12-03 17:20:46 -05:00
}
if ! info . BridgeNfIptables {
2015-12-11 14:23:16 -05:00
fmt . Fprintln ( cli . err , "WARNING: bridge-nf-call-iptables is disabled" )
2015-12-03 17:20:46 -05:00
}
if ! info . BridgeNfIP6tables {
2015-12-11 14:23:16 -05:00
fmt . Fprintln ( cli . err , "WARNING: bridge-nf-call-ip6tables is disabled" )
2015-07-09 22:05:50 -04:00
}
2015-06-16 21:19:11 -04:00
}
2015-07-09 22:05:50 -04:00
2015-04-10 13:26:30 -04:00
if info . Labels != nil {
2015-03-24 23:57:23 -04:00
fmt . Fprintln ( cli . out , "Labels:" )
2015-04-10 13:26:30 -04:00
for _ , attribute := range info . Labels {
2015-03-24 23:57:23 -04:00
fmt . Fprintf ( cli . out , " %s\n" , attribute )
}
}
2015-05-21 13:48:36 -04:00
2015-09-18 22:36:10 -04:00
ioutils . FprintfIfTrue ( cli . out , "Experimental: %v\n" , info . ExperimentalBuild )
2015-09-10 19:12:00 -04:00
if info . ClusterStore != "" {
2016-03-28 03:46:53 -04:00
fmt . Fprintf ( cli . out , "Cluster Store: %s\n" , info . ClusterStore )
2015-09-10 19:12:00 -04:00
}
2015-03-24 23:57:23 -04:00
2015-10-25 20:12:22 -04:00
if info . ClusterAdvertise != "" {
2016-03-28 03:46:53 -04:00
fmt . Fprintf ( cli . out , "Cluster Advertise: %s\n" , info . ClusterAdvertise )
2015-10-25 20:12:22 -04:00
}
2016-02-16 17:45:48 -05:00
if info . RegistryConfig != nil && ( len ( info . RegistryConfig . InsecureRegistryCIDRs ) > 0 || len ( info . RegistryConfig . IndexConfigs ) > 0 ) {
2016-04-25 06:40:24 -04:00
fmt . Fprintln ( cli . out , "Insecure Registries:" )
2016-02-16 17:45:48 -05:00
for _ , registry := range info . RegistryConfig . IndexConfigs {
if registry . Secure == false {
fmt . Fprintf ( cli . out , " %s\n" , registry . Name )
}
}
for _ , registry := range info . RegistryConfig . InsecureRegistryCIDRs {
mask , _ := registry . Mask . Size ( )
fmt . Fprintf ( cli . out , " %s/%d\n" , registry . IP . String ( ) , mask )
}
}
2015-03-24 23:57:23 -04:00
return nil
}