浏览代码

Merge pull request #15796 from azurezk/add-size-to-inspect

add container size info to inspect
Vincent Demeester 9 年之前
父节点
当前提交
ce607916e9

+ 8 - 1
api/client/inspect.go

@@ -5,6 +5,7 @@ import (
 	"encoding/json"
 	"fmt"
 	"io"
+	"net/url"
 	"strings"
 	"text/template"
 
@@ -27,6 +28,7 @@ func (cli *DockerCli) CmdInspect(args ...string) error {
 	cmd := Cli.Subcmd("inspect", []string{"CONTAINER|IMAGE [CONTAINER|IMAGE...]"}, Cli.DockerCommands["inspect"].Description, true)
 	tmplStr := cmd.String([]string{"f", "#format", "-format"}, "", "Format the output using the given go template")
 	inspectType := cmd.String([]string{"-type"}, "", "Return JSON for specified type, (e.g image or container)")
+	size := cmd.Bool([]string{"s", "-size"}, false, "Display total file sizes if the type is container")
 	cmd.Require(flag.Min, 1)
 
 	cmd.ParseFlags(args, true)
@@ -51,10 +53,15 @@ func (cli *DockerCli) CmdInspect(args ...string) error {
 	status := 0
 	isImage := false
 
+	v := url.Values{}
+	if *size {
+		v.Set("size", "1")
+	}
+
 	for _, name := range cmd.Args() {
 
 		if *inspectType == "" || *inspectType == "container" {
-			obj, _, err = readBody(cli.call("GET", "/containers/"+name+"/json", nil, nil))
+			obj, _, err = readBody(cli.call("GET", "/containers/"+name+"/json?"+v.Encode(), nil, nil))
 			if err != nil && *inspectType == "container" {
 				if strings.Contains(err.Error(), "No such") {
 					fmt.Fprintf(cli.err, "Error: No such container: %s\n", name)

+ 2 - 1
api/server/router/local/inspect.go

@@ -10,6 +10,7 @@ import (
 
 // getContainersByName inspects containers configuration and serializes it as json.
 func (s *router) getContainersByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+	displaySize := httputils.BoolValue(r, "size")
 	if vars == nil {
 		return fmt.Errorf("Missing parameter")
 	}
@@ -25,7 +26,7 @@ func (s *router) getContainersByName(ctx context.Context, w http.ResponseWriter,
 	case version.Equal("1.20"):
 		json, err = s.daemon.ContainerInspect120(vars["name"])
 	default:
-		json, err = s.daemon.ContainerInspect(vars["name"])
+		json, err = s.daemon.ContainerInspect(vars["name"], displaySize)
 	}
 
 	if err != nil {

+ 2 - 0
api/types/types.go

@@ -269,6 +269,8 @@ type ContainerJSONBase struct {
 	ExecIDs         []string
 	HostConfig      *runconfig.HostConfig
 	GraphDriver     GraphDriverData
+	SizeRw          *int64 `json:",omitempty"`
+	SizeRootFs      *int64 `json:",omitempty"`
 }
 
 // ContainerJSON is newly used struct along with MountPoint

+ 1 - 0
contrib/completion/fish/docker.fish

@@ -207,6 +207,7 @@ complete -c docker -f -n '__fish_docker_no_subcommand' -a info -d 'Display syste
 complete -c docker -f -n '__fish_docker_no_subcommand' -a inspect -d 'Return low-level information on a container or image'
 complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -s f -l format -d 'Format the output using the given go template.'
 complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -l help -d 'Print usage'
+complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -s s -l size -d 'Display total file sizes if the type is container.'
 complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -a '(__fish_print_docker_images)' -d "Image"
 complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -a '(__fish_print_docker_containers all)' -d "Container"
 

+ 1 - 0
contrib/completion/zsh/_docker

@@ -650,6 +650,7 @@ __docker_subcommand() {
             _arguments \
                 $opts_help \
                 "($help -f --format=-)"{-f,--format=-}"[Format the output using the given go template]:template: " \
+                "($help -s --size)"{-s,--size}"[Display total file sizes if the type is container]" \
                 "($help)--type=-[Return JSON for specified type]:type:(image container)" \
                 "($help -)*: :->values" && ret=0
 

+ 14 - 4
daemon/inspect.go

@@ -11,7 +11,7 @@ import (
 // ContainerInspect returns low-level information about a
 // container. Returns an error if the container cannot be found, or if
 // there is an error getting the data.
-func (daemon *Daemon) ContainerInspect(name string) (*types.ContainerJSON, error) {
+func (daemon *Daemon) ContainerInspect(name string, size bool) (*types.ContainerJSON, error) {
 	container, err := daemon.Get(name)
 	if err != nil {
 		return nil, err
@@ -20,7 +20,7 @@ func (daemon *Daemon) ContainerInspect(name string) (*types.ContainerJSON, error
 	container.Lock()
 	defer container.Unlock()
 
-	base, err := daemon.getInspectData(container)
+	base, err := daemon.getInspectData(container, size)
 	if err != nil {
 		return nil, err
 	}
@@ -40,7 +40,7 @@ func (daemon *Daemon) ContainerInspect120(name string) (*v1p20.ContainerJSON, er
 	container.Lock()
 	defer container.Unlock()
 
-	base, err := daemon.getInspectData(container)
+	base, err := daemon.getInspectData(container, false)
 	if err != nil {
 		return nil, err
 	}
@@ -54,7 +54,7 @@ func (daemon *Daemon) ContainerInspect120(name string) (*v1p20.ContainerJSON, er
 	return &v1p20.ContainerJSON{base, mountPoints, config}, nil
 }
 
-func (daemon *Daemon) getInspectData(container *Container) (*types.ContainerJSONBase, error) {
+func (daemon *Daemon) getInspectData(container *Container, size bool) (*types.ContainerJSONBase, error) {
 	// make a copy to play with
 	hostConfig := *container.hostConfig
 
@@ -106,6 +106,16 @@ func (daemon *Daemon) getInspectData(container *Container) (*types.ContainerJSON
 		HostConfig:      &hostConfig,
 	}
 
+	var (
+		sizeRw     int64
+		sizeRootFs int64
+	)
+	if size {
+		sizeRw, sizeRootFs = container.getSize()
+		contJSONBase.SizeRw = &sizeRw
+		contJSONBase.SizeRootFs = &sizeRootFs
+	}
+
 	// Now set any platform-specific fields
 	contJSONBase = setPlatformSpecificContainerFields(container, contJSONBase)
 

+ 1 - 1
daemon/inspect_unix.go

@@ -27,7 +27,7 @@ func (daemon *Daemon) ContainerInspectPre120(name string) (*v1p19.ContainerJSON,
 	container.Lock()
 	defer container.Unlock()
 
-	base, err := daemon.getInspectData(container)
+	base, err := daemon.getInspectData(container, false)
 	if err != nil {
 		return nil, err
 	}

+ 1 - 1
daemon/inspect_windows.go

@@ -13,5 +13,5 @@ func addMountPoints(container *Container) []types.MountPoint {
 
 // ContainerInspectPre120 get containers for pre 1.20 APIs.
 func (daemon *Daemon) ContainerInspectPre120(name string) (*types.ContainerJSON, error) {
-	return daemon.ContainerInspect(name)
+	return daemon.ContainerInspect(name, false)
 }

+ 1 - 0
docs/reference/api/docker_remote_api.md

@@ -109,6 +109,7 @@ list of DNS options to be used in the container.
 * `GET /info` now lists engine version information.
 * `GET /containers/json` will return `ImageID` of the image used by container.
 * `POST /exec/(name)/start` will now return an HTTP 409 when the container is either stopped or paused.
+* `GET /containers/(name)/json` now accepts a `size` parameter. Setting this parameter to '1' returns container size information in the `SizeRw` and `SizeRootFs` fields.
 
 ### v1.20 API changes
 

+ 20 - 0
docs/reference/api/docker_remote_api_v1.21.md

@@ -467,6 +467,26 @@ Return low-level information on the container `id`
 		]
 	}
 
+**Example request, with size information**:
+
+    GET /containers/4fa6e0f0c678/json?size=1 HTTP/1.1
+
+**Example response, with size information**:
+
+    HTTP/1.1 200 OK
+    Content-Type: application/json
+
+    {
+    ....
+    "SizeRw": 0,
+    "SizeRootFs": 972,
+    ....
+    }
+
+Query Parameters:
+
+-   **size** – 1/True/true or 0/False/false, return container size information. Default is `false`.
+
 Status Codes:
 
 -   **200** – no error

+ 1 - 0
docs/reference/commandline/inspect.md

@@ -18,6 +18,7 @@ parent = "smn_cli"
       --help=false            Print usage
       --type=container|image  Return JSON for specified type, permissible
                               values are "image" or "container"
+      -s, --size=false        Display total file sizes if the type is container
 
 By default, this will render all results in a JSON array. If a format is
 specified, the given template will be executed for each result.

+ 40 - 0
integration-cli/docker_cli_inspect_test.go

@@ -345,3 +345,43 @@ func (s *DockerSuite) TestInspectLogConfigNoType(c *check.C) {
 	c.Assert(logConfig.Type, check.Equals, "json-file")
 	c.Assert(logConfig.Config["max-file"], check.Equals, "42", check.Commentf("%v", logConfig))
 }
+
+func (s *DockerSuite) TestInspectNoSizeFlagContainer(c *check.C) {
+
+	//Both the container and image are named busybox. docker inspect will fetch container
+	//JSON SizeRw and SizeRootFs field. If there is no flag --size/-s, there are no size fields.
+
+	dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "top")
+
+	formatStr := fmt.Sprintf("--format='{{.SizeRw}},{{.SizeRootFs}}'")
+	out, _ := dockerCmd(c, "inspect", "--type=container", formatStr, "busybox")
+	c.Assert(strings.TrimSpace(out), check.Equals, "<nil>,<nil>", check.Commentf("Exepcted not to display size info: %s", out))
+}
+
+func (s *DockerSuite) TestInspectSizeFlagContainer(c *check.C) {
+
+	//Both the container and image are named busybox. docker inspect will fetch container
+	//JSON SizeRw and SizeRootFs field. If there is a flag --size/-s, the fields are not <no value>.
+
+	dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "top")
+
+	formatStr := fmt.Sprintf("--format='{{.SizeRw}},{{.SizeRootFs}}'")
+	out, _ := dockerCmd(c, "inspect", "-s", "--type=container", formatStr, "busybox")
+	sz := strings.Split(out, ",")
+
+	c.Assert(strings.TrimSpace(sz[0]), check.Not(check.Equals), "<nil>")
+	c.Assert(strings.TrimSpace(sz[1]), check.Not(check.Equals), "<nil>")
+}
+
+func (s *DockerSuite) TestInspectSizeFlagImage(c *check.C) {
+
+	//Both the container and image are named busybox. docker inspect will fetch image
+	//JSON SizeRw and SizeRootFs field. There are no these fields since they are only in containers.
+
+	dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "top")
+
+	formatStr := fmt.Sprintf("--format='{{.SizeRw}},{{.SizeRootFs}}'")
+	out, _ := dockerCmd(c, "inspect", "-s", "--type=image", formatStr, "busybox")
+
+	c.Assert(strings.TrimSpace(out), check.Equals, "<no value>,<no value>", check.Commentf("Fields SizeRw and SizeRootFs are not exepcted to exist"))
+}

+ 16 - 0
man/docker-inspect.1.md

@@ -8,6 +8,7 @@ docker-inspect - Return low-level information on a container or image
 **docker inspect**
 [**--help**]
 [**-f**|**--format**[=*FORMAT*]]
+[**-s**|**--size**[=*false*]]
 [**--type**=*container*|*image*]
 CONTAINER|IMAGE [CONTAINER|IMAGE...]
 
@@ -25,6 +26,9 @@ each result.
 **-f**, **--format**=""
     Format the output using the given Go template.
 
+**-s**, **--size**=false
+    Display total file sizes if the type is container.
+
 **--type**=*container*|*image*
     Return JSON for specified type, permissible values are "image" or "container"
 
@@ -205,6 +209,18 @@ output:
 You can get more information about how to write a Go template from:
 https://golang.org/pkg/text/template/.
 
+## Getting size information on an container
+
+    $ docker inspect -s d2cc496561d6
+    [
+    {
+    ....
+    "SizeRw": 0,
+    "SizeRootFs": 972,
+    ....
+    }
+    ]
+
 ## Getting information on an image
 
 Use an image's ID or name (e.g., repository/name[:tag]) to get information