From 407a626be62996cd6385ea4d80e669ab83f5f04d Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Mon, 15 Jun 2015 14:05:10 -0400 Subject: [PATCH] docker-inspect: Extend docker inspect to export image/container metadata related to graph driver Export image/container metadata stored in graph driver. Right now 3 fields DeviceId, DeviceSize and DeviceName are being exported from devicemapper. Other graph drivers can export fields as they see fit. This data can be used to mount the thin device outside of docker and tools can look into image/container and do some kind of inspection. Signed-off-by: Vivek Goyal --- api/types/types.go | 7 + daemon/graphdriver/aufs/aufs.go | 4 + daemon/graphdriver/btrfs/btrfs.go | 4 + daemon/graphdriver/devmapper/deviceset.go | 21 ++ daemon/graphdriver/devmapper/driver.go | 15 + daemon/graphdriver/driver.go | 3 + daemon/graphdriver/overlay/overlay.go | 4 + daemon/graphdriver/vfs/driver.go | 4 + daemon/graphdriver/zfs/zfs.go | 4 + daemon/inspect.go | 7 + graph/service.go | 7 + integration-cli/docker_api_inspect_test.go | 2 +- integration-cli/docker_cli_inspect_test.go | 67 ++++ man/docker-inspect.1.md | 409 +++++++++++---------- 14 files changed, 353 insertions(+), 205 deletions(-) diff --git a/api/types/types.go b/api/types/types.go index b885242a2b..86daa126d1 100644 --- a/api/types/types.go +++ b/api/types/types.go @@ -75,6 +75,11 @@ type Image struct { Labels map[string]string } +type GraphDriverData struct { + Name string + Data map[string]string +} + // GET "/images/{name:.*}/json" type ImageInspect struct { Id string @@ -90,6 +95,7 @@ type ImageInspect struct { Os string Size int64 VirtualSize int64 + GraphDriver GraphDriverData } // GET "/containers/json" @@ -218,6 +224,7 @@ type ContainerJSONBase struct { AppArmorProfile string ExecIDs []string HostConfig *runconfig.HostConfig + GraphDriver GraphDriverData } type ContainerJSON struct { diff --git a/daemon/graphdriver/aufs/aufs.go b/daemon/graphdriver/aufs/aufs.go index ecbbdf8187..1d208d54fc 100644 --- a/daemon/graphdriver/aufs/aufs.go +++ b/daemon/graphdriver/aufs/aufs.go @@ -162,6 +162,10 @@ func (a *Driver) Status() [][2]string { } } +func (a *Driver) GetMetadata(id string) (map[string]string, error) { + return nil, nil +} + // Exists returns true if the given id is registered with // this driver func (a *Driver) Exists(id string) bool { diff --git a/daemon/graphdriver/btrfs/btrfs.go b/daemon/graphdriver/btrfs/btrfs.go index 1830ad4e8f..044a9c27fd 100644 --- a/daemon/graphdriver/btrfs/btrfs.go +++ b/daemon/graphdriver/btrfs/btrfs.go @@ -70,6 +70,10 @@ func (d *Driver) Status() [][2]string { return status } +func (d *Driver) GetMetadata(id string) (map[string]string, error) { + return nil, nil +} + func (d *Driver) Cleanup() error { return mount.Unmount(d.home) } diff --git a/daemon/graphdriver/devmapper/deviceset.go b/daemon/graphdriver/devmapper/deviceset.go index 24805179f8..47affb8275 100644 --- a/daemon/graphdriver/devmapper/deviceset.go +++ b/daemon/graphdriver/devmapper/deviceset.go @@ -127,6 +127,13 @@ type Status struct { DeferredRemoveEnabled bool } +// Structure used to export image/container metadata in docker inspect. +type DeviceMetadata struct { + deviceId int + deviceSize uint64 // size in bytes + deviceName string // Device name as used during activation +} + type DevStatus struct { DeviceId int Size uint64 @@ -1700,6 +1707,20 @@ func (devices *DeviceSet) Status() *Status { return status } +// Status returns the current status of this deviceset +func (devices *DeviceSet) ExportDeviceMetadata(hash string) (*DeviceMetadata, error) { + info, err := devices.lookupDevice(hash) + if err != nil { + return nil, err + } + + info.lock.Lock() + defer info.lock.Unlock() + + metadata := &DeviceMetadata{info.DeviceId, info.Size, info.Name()} + return metadata, nil +} + func NewDeviceSet(root string, doInit bool, options []string) (*DeviceSet, error) { devicemapper.SetDevDir("/dev") diff --git a/daemon/graphdriver/devmapper/driver.go b/daemon/graphdriver/devmapper/driver.go index bdf7f874f9..237c4b04d3 100644 --- a/daemon/graphdriver/devmapper/driver.go +++ b/daemon/graphdriver/devmapper/driver.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "os" "path" + "strconv" "github.com/Sirupsen/logrus" "github.com/docker/docker/daemon/graphdriver" @@ -91,6 +92,20 @@ func (d *Driver) Status() [][2]string { return status } +func (d *Driver) GetMetadata(id string) (map[string]string, error) { + m, err := d.DeviceSet.ExportDeviceMetadata(id) + + if err != nil { + return nil, err + } + + metadata := make(map[string]string) + metadata["DeviceId"] = strconv.Itoa(m.deviceId) + metadata["DeviceSize"] = strconv.FormatUint(m.deviceSize, 10) + metadata["DeviceName"] = m.deviceName + return metadata, nil +} + func (d *Driver) Cleanup() error { err := d.DeviceSet.Shutdown() diff --git a/daemon/graphdriver/driver.go b/daemon/graphdriver/driver.go index 963acdfbb1..68e1383b15 100644 --- a/daemon/graphdriver/driver.go +++ b/daemon/graphdriver/driver.go @@ -56,6 +56,9 @@ type ProtoDriver interface { // Status returns a set of key-value pairs which give low // level diagnostic status about this driver. Status() [][2]string + // Returns a set of key-value pairs which give low level information + // about the image/container driver is managing. + GetMetadata(id string) (map[string]string, error) // Cleanup performs necessary tasks to release resources // held by the driver, e.g., unmounting all layered filesystems // known to this driver. diff --git a/daemon/graphdriver/overlay/overlay.go b/daemon/graphdriver/overlay/overlay.go index df6a7dbd93..1fbe51ade0 100644 --- a/daemon/graphdriver/overlay/overlay.go +++ b/daemon/graphdriver/overlay/overlay.go @@ -167,6 +167,10 @@ func (d *Driver) Status() [][2]string { } } +func (d *Driver) GetMetadata(id string) (map[string]string, error) { + return nil, nil +} + func (d *Driver) Cleanup() error { return nil } diff --git a/daemon/graphdriver/vfs/driver.go b/daemon/graphdriver/vfs/driver.go index 63c93ac30d..a7dc7dfa54 100644 --- a/daemon/graphdriver/vfs/driver.go +++ b/daemon/graphdriver/vfs/driver.go @@ -36,6 +36,10 @@ func (d *Driver) Status() [][2]string { return nil } +func (d *Driver) GetMetadata(id string) (map[string]string, error) { + return nil, nil +} + func (d *Driver) Cleanup() error { return nil } diff --git a/daemon/graphdriver/zfs/zfs.go b/daemon/graphdriver/zfs/zfs.go index d08645291d..287a530d0c 100644 --- a/daemon/graphdriver/zfs/zfs.go +++ b/daemon/graphdriver/zfs/zfs.go @@ -186,6 +186,10 @@ func (d *Driver) Status() [][2]string { } } +func (d *Driver) GetMetadata(id string) (map[string]string, error) { + return nil, nil +} + func (d *Driver) cloneFilesystem(name, parentName string) error { snapshotName := fmt.Sprintf("%d", time.Now().Nanosecond()) parentDataset := zfs.Dataset{Name: parentName} diff --git a/daemon/inspect.go b/daemon/inspect.go index c935c2b8cd..73b394ca24 100644 --- a/daemon/inspect.go +++ b/daemon/inspect.go @@ -109,6 +109,13 @@ func (daemon *Daemon) getInspectData(container *Container) (*types.ContainerJSON HostConfig: &hostConfig, } + contJSONBase.GraphDriver.Name = container.Driver + graphDriverData, err := daemon.driver.GetMetadata(container.ID) + if err != nil { + return nil, err + } + contJSONBase.GraphDriver.Data = graphDriverData + return contJSONBase, nil } diff --git a/graph/service.go b/graph/service.go index 7718bab769..7e4bb382c5 100644 --- a/graph/service.go +++ b/graph/service.go @@ -45,6 +45,13 @@ func (s *TagStore) Lookup(name string) (*types.ImageInspect, error) { VirtualSize: s.graph.GetParentsSize(image, 0) + image.Size, } + imageInspect.GraphDriver.Name = s.graph.driver.String() + + graphDriverData, err := s.graph.driver.GetMetadata(image.ID) + if err != nil { + return nil, err + } + imageInspect.GraphDriver.Data = graphDriverData return imageInspect, nil } diff --git a/integration-cli/docker_api_inspect_test.go b/integration-cli/docker_api_inspect_test.go index 62f32357ce..e79c845d69 100644 --- a/integration-cli/docker_api_inspect_test.go +++ b/integration-cli/docker_api_inspect_test.go @@ -28,7 +28,7 @@ func (s *DockerSuite) TestInspectApiContainerResponse(c *check.C) { c.Fatalf("unable to unmarshal body for latest version: %v", err) } - keys := []string{"State", "Created", "Path", "Args", "Config", "Image", "NetworkSettings", "ResolvConfPath", "HostnamePath", "HostsPath", "LogPath", "Name", "Driver", "ExecDriver", "MountLabel", "ProcessLabel", "Volumes", "VolumesRW"} + keys := []string{"State", "Created", "Path", "Args", "Config", "Image", "NetworkSettings", "ResolvConfPath", "HostnamePath", "HostsPath", "LogPath", "Name", "Driver", "ExecDriver", "MountLabel", "ProcessLabel", "Volumes", "VolumesRW", "GraphDriver"} keys = append(keys, "Id") diff --git a/integration-cli/docker_cli_inspect_test.go b/integration-cli/docker_cli_inspect_test.go index 066e014b4d..d40a57a47b 100644 --- a/integration-cli/docker_cli_inspect_test.go +++ b/integration-cli/docker_cli_inspect_test.go @@ -89,3 +89,70 @@ func (s *DockerSuite) TestInspectContainerFilterInt(c *check.C) { c.Fatalf("Expected exitcode: %d for container: %s", exitCode, id) } } + +func (s *DockerSuite) TestInspectImageGraphDriver(c *check.C) { + imageTest := "emptyfs" + name, err := inspectField(imageTest, "GraphDriver.Name") + c.Assert(err, check.IsNil) + + if name != "devicemapper" && name != "overlay" && name != "vfs" && name != "zfs" && name != "btrfs" && name != "aufs" { + c.Fatalf("%v is not a valid graph driver name", name) + } + + if name != "devicemapper" { + return + } + + deviceId, err := inspectField(imageTest, "GraphDriver.Data.DeviceId") + c.Assert(err, check.IsNil) + + _, err = strconv.Atoi(deviceId) + if err != nil { + c.Fatalf("failed to inspect DeviceId of the image: %s, %v", deviceId, err) + } + + deviceSize, err := inspectField(imageTest, "GraphDriver.Data.DeviceSize") + c.Assert(err, check.IsNil) + + _, err = strconv.ParseUint(deviceSize, 10, 64) + if err != nil { + c.Fatalf("failed to inspect DeviceSize of the image: %s, %v", deviceSize, err) + } +} + +func (s *DockerSuite) TestInspectContainerGraphDriver(c *check.C) { + runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true") + out, _, _, err := runCommandWithStdoutStderr(runCmd) + if err != nil { + c.Fatalf("failed to run container: %v, output: %q", err, out) + } + + out = strings.TrimSpace(out) + + name, err := inspectField(out, "GraphDriver.Name") + c.Assert(err, check.IsNil) + + if name != "devicemapper" && name != "overlay" && name != "vfs" && name != "zfs" && name != "btrfs" && name != "aufs" { + c.Fatalf("%v is not a valid graph driver name", name) + } + + if name != "devicemapper" { + return + } + + deviceId, err := inspectField(out, "GraphDriver.Data.DeviceId") + c.Assert(err, check.IsNil) + + _, err = strconv.Atoi(deviceId) + if err != nil { + c.Fatalf("failed to inspect DeviceId of the image: %s, %v", deviceId, err) + } + + deviceSize, err := inspectField(out, "GraphDriver.Data.DeviceSize") + c.Assert(err, check.IsNil) + + _, err = strconv.ParseUint(deviceSize, 10, 64) + if err != nil { + c.Fatalf("failed to inspect DeviceSize of the image: %s, %v", deviceSize, err) + } +} diff --git a/man/docker-inspect.1.md b/man/docker-inspect.1.md index a8a2d8f493..1b87ef088e 100644 --- a/man/docker-inspect.1.md +++ b/man/docker-inspect.1.md @@ -30,143 +30,144 @@ each result. To get information on a container use its ID or instance name: - $ docker inspect 1eb5fabf5a03 - [{ - "AppArmorProfile": "", - "Args": [], - "Config": { - "AttachStderr": false, - "AttachStdin": false, - "AttachStdout": false, - "Cmd": [ - "/usr/sbin/nginx" - ], - "Domainname": "", - "Entrypoint": null, - "Env": [ - "HOME=/", - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - ], - "ExposedPorts": { - "80/tcp": {} - }, - "Hostname": "1eb5fabf5a03", - "Image": "summit/nginx", - "Labels": { - "com.example.vendor": "Acme", - "com.example.license": "GPL", - "com.example.version": "1.0" - }, - "MacAddress": "", - "NetworkDisabled": false, - "OnBuild": null, - "OpenStdin": false, - "StdinOnce": false, - "Tty": true, - "User": "", - "Volumes": null, - "WorkingDir": "", + $ docker inspect d2cc496561d6 +[{ + "Id": "d2cc496561d6d520cbc0236b4ba88c362c446a7619992123f11c809cded25b47", + "Created": "2015-06-08T16:18:02.505155285Z", + "Path": "bash", + "Args": [], + "State": { + "Running": false, + "Paused": false, + "Restarting": false, + "OOMKilled": false, + "Dead": false, + "Pid": 0, + "ExitCode": 0, + "Error": "", + "StartedAt": "2015-06-08T16:18:03.643865954Z", + "FinishedAt": "2015-06-08T16:57:06.448552862Z" + }, + "Image": "ded7cd95e059788f2586a51c275a4f151653779d6a7f4dad77c2bd34601d94e4", + "NetworkSettings": { + "Bridge": "", + "EndpointID": "", + "Gateway": "", + "GlobalIPv6Address": "", + "GlobalIPv6PrefixLen": 0, + "HairpinMode": false, + "IPAddress": "", + "IPPrefixLen": 0, + "IPv6Gateway": "", + "LinkLocalIPv6Address": "", + "LinkLocalIPv6PrefixLen": 0, + "MacAddress": "", + "NetworkID": "", + "PortMapping": null, + "Ports": null, + "SandboxKey": "", + "SecondaryIPAddresses": null, + "SecondaryIPv6Addresses": null + }, + "ResolvConfPath": "/var/lib/docker/containers/d2cc496561d6d520cbc0236b4ba88c362c446a7619992123f11c809cded25b47/resolv.conf", + "HostnamePath": "/var/lib/docker/containers/d2cc496561d6d520cbc0236b4ba88c362c446a7619992123f11c809cded25b47/hostname", + "HostsPath": "/var/lib/docker/containers/d2cc496561d6d520cbc0236b4ba88c362c446a7619992123f11c809cded25b47/hosts", + "LogPath": "/var/lib/docker/containers/d2cc496561d6d520cbc0236b4ba88c362c446a7619992123f11c809cded25b47/d2cc496561d6d520cbc0236b4ba88c362c446a7619992123f11c809cded25b47-json.log", + "Name": "/adoring_wozniak", + "RestartCount": 0, + "Driver": "devicemapper", + "ExecDriver": "native-0.2", + "MountLabel": "", + "ProcessLabel": "", + "Volumes": {}, + "VolumesRW": {}, + "AppArmorProfile": "", + "ExecIDs": null, + "HostConfig": { + "Binds": null, + "ContainerIDFile": "", + "LxcConf": [], + "Memory": 0, + "MemorySwap": 0, + "CpuShares": 0, + "CpuPeriod": 0, + "CpusetCpus": "", + "CpusetMems": "", + "CpuQuota": 0, + "BlkioWeight": 0, + "OomKillDisable": false, + "Privileged": false, + "PortBindings": {}, + "Links": null, + "PublishAllPorts": false, + "Dns": null, + "DnsSearch": null, + "ExtraHosts": null, + "VolumesFrom": null, + "Devices": [], + "NetworkMode": "bridge", + "IpcMode": "", + "PidMode": "", + "UTSMode": "", + "CapAdd": null, + "CapDrop": null, + "RestartPolicy": { + "Name": "no", + "MaximumRetryCount": 0 }, - "Created": "2014-04-04T21:33:52.02361335Z", - "Driver": "devicemapper", - "ExecDriver": "native-0.1", - "ExecIDs": null, - "HostConfig": { - "Binds": null, - "CapAdd": null, - "CapDrop": null, - "CgroupParent": "", - "ContainerIDFile": "", - "CpuShares": 512, - "CpusetCpus": "0,1", - "CpusetMems": "", - "Devices": [], - "Dns": null, - "DnsSearch": null, - "ExtraHosts": null, - "IpcMode": "", - "Links": null, - "LogConfig": { - "Config": null, - "Type": "json-file" - }, - "LxcConf": null, - "Memory": 16777216, - "MemorySwap": -1, - "NetworkMode": "", - "PidMode": "", - "PortBindings": { - "80/tcp": [ - { - "HostIp": "0.0.0.0", - "HostPort": "80" - } - ] - }, - "Privileged": false, - "PublishAllPorts": false, - "ReadonlyRootfs": false, - "RestartPolicy": { - "MaximumRetryCount": 0, - "Name": "" - }, - "SecurityOpt": null, - "Ulimits": null, - "VolumesFrom": null + "SecurityOpt": null, + "ReadonlyRootfs": false, + "Ulimits": null, + "LogConfig": { + "Type": "json-file", + "Config": {} + }, + "CgroupParent": "" + }, + "GraphDriver": { + "Name": "devicemapper", + "Data": { + "DeviceId": "5", + "DeviceName": "docker-253:1-2763198-d2cc496561d6d520cbc0236b4ba88c362c446a7619992123f11c809cded25b47", + "DeviceSize": "171798691840" } - "HostnamePath": "/var/lib/docker/containers/1eb5fabf5a03807136561b3c00adcd2992b535d624d5e18b6cdc6a6844d9767b/hostname", - "HostsPath": "/var/lib/docker/containers/1eb5fabf5a03807136561b3c00adcd2992b535d624d5e18b6cdc6a6844d9767b/hosts", - "ID": "1eb5fabf5a03807136561b3c00adcd2992b535d624d5e18b6cdc6a6844d9767b", - "Image": "df53773a4390e25936f9fd3739e0c0e60a62d024ea7b669282b27e65ae8458e6", - "LogPath": "/var/lib/docker/containers/1eb5fabf5a03807136561b3c00adcd2992b535d624d5e18b6cdc6a6844d9767b/1eb5fabf5a03807136561b3c00adcd2992b535d624d5e18b6cdc6a6844d9767b-json.log", - "MountLabel": "", - "Name": "/ecstatic_ptolemy", - "NetworkSettings": { - "Bridge": "docker0", - "Gateway": "172.17.42.1", - "GlobalIPv6Address": "", - "GlobalIPv6PrefixLen": 0, - "IPAddress": "172.17.0.2", - "IPPrefixLen": 16, - "IPv6Gateway": "", - "LinkLocalIPv6Address": "", - "LinkLocalIPv6PrefixLen": 0, - "MacAddress": "", - "PortMapping": null, - "Ports": { - "80/tcp": [ - { - "HostIp": "0.0.0.0", - "HostPort": "80" - } - ] - } - }, - "Path": "/usr/sbin/nginx", - "ProcessLabel": "", - "ResolvConfPath": "/etc/resolv.conf", - "RestartCount": 0, - "State": { - "Dead": false, - "Error": "", - "ExitCode": 0, - "FinishedAt": "0001-01-01T00:00:00Z", - "OOMKilled": false, - "Paused": false, - "Pid": 858, - "Restarting": false, - "Running": true, - "StartedAt": "2014-04-04T21:33:54.16259207Z", - }, - "Volumes": {}, - "VolumesRW": {}, + }, + "Config": { + "Hostname": "d2cc496561d6", + "Domainname": "", + "User": "", + "AttachStdin": true, + "AttachStdout": true, + "AttachStderr": true, + "ExposedPorts": null, + "Tty": true, + "OpenStdin": true, + "StdinOnce": true, + "Env": null, + "Cmd": [ + "bash" + ], + "Image": "fedora", + "Volumes": null, + "VolumeDriver": "", + "WorkingDir": "", + "Entrypoint": null, + "NetworkDisabled": false, + "MacAddress": "", + "OnBuild": null, + "Labels": {}, + "Memory": 0, + "MemorySwap": 0, + "CpuShares": 0, + "Cpuset": "" } - +} +] ## Getting the IP address of a container instance To get the IP address of a container use: - $ docker inspect --format='{{.NetworkSettings.IPAddress}}' 1eb5fabf5a03 + $ docker inspect --format='{{.NetworkSettings.IPAddress}}' d2cc496561d6 172.17.0.2 ## Listing all port bindings @@ -175,7 +176,7 @@ One can loop over arrays and maps in the results to produce simple text output: $ docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}} \ - {{$p}} -> {{(index $conf 0).HostPort}} {{end}}' 1eb5fabf5a03 + {{$p}} -> {{(index $conf 0).HostPort}} {{end}}' d2cc496561d6 80/tcp -> 80 You can get more information about how to write a go template from: @@ -186,79 +187,79 @@ http://golang.org/pkg/text/template/. Use an image's ID or name (e.g., repository/name[:tag]) to get information on it. - $ docker inspect fc1203419df2 - [{ - "Architecture": "amd64", - "Author": "", - "Comment": "", - "Config": { - "AttachStderr": false, - "AttachStdin": false, - "AttachStdout": false, - "Cmd": [ - "make", - "direct-test" - ], - "Domainname": "", - "Entrypoint": [ - "/dind" - ], - "Env": [ - "PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", - ], - "ExposedPorts": null, - "Hostname": "242978536a06", - "Image": "c2b774c744afc5bea603b5e6c5218539e506649326de3ea0135182f299d0519a", - "Labels": {}, - "MacAddress": "", - "NetworkDisabled": false, - "OnBuild": [], - "OpenStdin": false, - "StdinOnce": false, - "Tty": false, - "User": "", - "Volumes": null, - "WorkingDir": "/go/src/github.com/docker/libcontainer" - }, - "Container": "1c00417f3812a96d3ebc29e7fdee69f3d586d703ab89c8233fd4678d50707b39", - "ContainerConfig": { - "AttachStderr": false, - "AttachStdin": false, - "AttachStdout": false, - "Cmd": [ - "/bin/sh", - "-c", - "#(nop) CMD [\"make\" \"direct-test\"]" - ], - "Domainname": "", - "Entrypoint": [ - "/dind" - ], - "Env": [ - "PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", - ], - "ExposedPorts": null, - "Hostname": "242978536a06", - "Image": "c2b774c744afc5bea603b5e6c5218539e506649326de3ea0135182f299d0519a", - "Labels": {}, - "MacAddress": "", - "NetworkDisabled": false, - "OnBuild": [], - "OpenStdin": false, - "StdinOnce": false, - "Tty": false, - "User": "", - "Volumes": null, - "WorkingDir": "/go/src/github.com/docker/libcontainer" - }, - "Created": "2015-04-07T05:34:39.079489206Z", - "DockerVersion": "1.5.0-dev", - "Id": "fc1203419df26ca82cad1dd04c709cb1b8a8a947bd5bcbdfbef8241a76f031db", - "Os": "linux", - "Parent": "c2b774c744afc5bea603b5e6c5218539e506649326de3ea0135182f299d0519a", - "Size": 0, - "VirtualSize": 613136466 - }] + $ docker inspect ded7cd95e059 +[{ + "Id": "ded7cd95e059788f2586a51c275a4f151653779d6a7f4dad77c2bd34601d94e4", + "Parent": "48ecf305d2cf7046c1f5f8fcbcd4994403173441d4a7f125b1bb0ceead9de731", + "Comment": "", + "Created": "2015-05-27T16:58:22.937503085Z", + "Container": "76cf7f67d83a7a047454b33007d03e32a8f474ad332c3a03c94537edd22b312b", + "ContainerConfig": { + "Hostname": "76cf7f67d83a", + "Domainname": "", + "User": "", + "AttachStdin": false, + "AttachStdout": false, + "AttachStderr": false, + "ExposedPorts": null, + "Tty": false, + "OpenStdin": false, + "StdinOnce": false, + "Env": null, + "Cmd": [ + "/bin/sh", + "-c", + "#(nop) ADD file:4be46382bcf2b095fcb9fe8334206b584eff60bb3fad8178cbd97697fcb2ea83 in /" + ], + "Image": "48ecf305d2cf7046c1f5f8fcbcd4994403173441d4a7f125b1bb0ceead9de731", + "Volumes": null, + "VolumeDriver": "", + "WorkingDir": "", + "Entrypoint": null, + "NetworkDisabled": false, + "MacAddress": "", + "OnBuild": null, + "Labels": {} + }, + "DockerVersion": "1.6.0", + "Author": "Lokesh Mandvekar \u003clsm5@fedoraproject.org\u003e", + "Config": { + "Hostname": "76cf7f67d83a", + "Domainname": "", + "User": "", + "AttachStdin": false, + "AttachStdout": false, + "AttachStderr": false, + "ExposedPorts": null, + "Tty": false, + "OpenStdin": false, + "StdinOnce": false, + "Env": null, + "Cmd": null, + "Image": "48ecf305d2cf7046c1f5f8fcbcd4994403173441d4a7f125b1bb0ceead9de731", + "Volumes": null, + "VolumeDriver": "", + "WorkingDir": "", + "Entrypoint": null, + "NetworkDisabled": false, + "MacAddress": "", + "OnBuild": null, + "Labels": {} + }, + "Architecture": "amd64", + "Os": "linux", + "Size": 186507296, + "VirtualSize": 186507296, + "GraphDriver": { + "Name": "devicemapper", + "Data": { + "DeviceId": "3", + "DeviceName": "docker-253:1-2763198-ded7cd95e059788f2586a51c275a4f151653779d6a7f4dad77c2bd34601d94e4", + "DeviceSize": "171798691840" + } + } +} +] # HISTORY April 2014, originally compiled by William Henry (whenry at redhat dot com)