diff --git a/api/client/inspect.go b/api/client/inspect.go index 66517c9514..766651d947 100644 --- a/api/client/inspect.go +++ b/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) diff --git a/api/server/router/local/inspect.go b/api/server/router/local/inspect.go index 67200b1ff6..b9bf697083 100644 --- a/api/server/router/local/inspect.go +++ b/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 { diff --git a/api/types/types.go b/api/types/types.go index 764878665c..a3a61a10b7 100644 --- a/api/types/types.go +++ b/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 diff --git a/contrib/completion/fish/docker.fish b/contrib/completion/fish/docker.fish index 17d2a06d77..144c489140 100644 --- a/contrib/completion/fish/docker.fish +++ b/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" diff --git a/contrib/completion/zsh/_docker b/contrib/completion/zsh/_docker index ced1a5eaef..089d220f3c 100644 --- a/contrib/completion/zsh/_docker +++ b/contrib/completion/zsh/_docker @@ -548,6 +548,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 diff --git a/daemon/inspect.go b/daemon/inspect.go index f3fbb82477..ad5463bd64 100644 --- a/daemon/inspect.go +++ b/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) diff --git a/daemon/inspect_unix.go b/daemon/inspect_unix.go index 2b5ebaba56..4e70f5904a 100644 --- a/daemon/inspect_unix.go +++ b/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 } diff --git a/daemon/inspect_windows.go b/daemon/inspect_windows.go index 34dceca609..654d78c35e 100644 --- a/daemon/inspect_windows.go +++ b/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) } diff --git a/docs/reference/api/docker_remote_api.md b/docs/reference/api/docker_remote_api.md index e7888bcb99..1a4a58a354 100644 --- a/docs/reference/api/docker_remote_api.md +++ b/docs/reference/api/docker_remote_api.md @@ -92,6 +92,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 diff --git a/docs/reference/api/docker_remote_api_v1.21.md b/docs/reference/api/docker_remote_api_v1.21.md index e549d87372..0ba92d8a6a 100644 --- a/docs/reference/api/docker_remote_api_v1.21.md +++ b/docs/reference/api/docker_remote_api_v1.21.md @@ -466,6 +466,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 diff --git a/docs/reference/commandline/inspect.md b/docs/reference/commandline/inspect.md index 998e198fe7..e9aea381ff 100644 --- a/docs/reference/commandline/inspect.md +++ b/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. diff --git a/integration-cli/docker_cli_inspect_test.go b/integration-cli/docker_cli_inspect_test.go index 97cf02de10..f4a8a0d39d 100644 --- a/integration-cli/docker_cli_inspect_test.go +++ b/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, ",", 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 . + + 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), "") + c.Assert(strings.TrimSpace(sz[1]), check.Not(check.Equals), "") +} + +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, ",", check.Commentf("Fields SizeRw and SizeRootFs are not exepcted to exist")) +} diff --git a/man/docker-inspect.1.md b/man/docker-inspect.1.md index 3d1db2ed3e..3a5168b979 100644 --- a/man/docker-inspect.1.md +++ b/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