add container size info to inspect
| ... | ... |
@@ -5,6 +5,7 @@ import ( |
| 5 | 5 |
"encoding/json" |
| 6 | 6 |
"fmt" |
| 7 | 7 |
"io" |
| 8 |
+ "net/url" |
|
| 8 | 9 |
"strings" |
| 9 | 10 |
"text/template" |
| 10 | 11 |
|
| ... | ... |
@@ -27,6 +28,7 @@ func (cli *DockerCli) CmdInspect(args ...string) error {
|
| 27 | 27 |
cmd := Cli.Subcmd("inspect", []string{"CONTAINER|IMAGE [CONTAINER|IMAGE...]"}, Cli.DockerCommands["inspect"].Description, true)
|
| 28 | 28 |
tmplStr := cmd.String([]string{"f", "#format", "-format"}, "", "Format the output using the given go template")
|
| 29 | 29 |
inspectType := cmd.String([]string{"-type"}, "", "Return JSON for specified type, (e.g image or container)")
|
| 30 |
+ size := cmd.Bool([]string{"s", "-size"}, false, "Display total file sizes if the type is container")
|
|
| 30 | 31 |
cmd.Require(flag.Min, 1) |
| 31 | 32 |
|
| 32 | 33 |
cmd.ParseFlags(args, true) |
| ... | ... |
@@ -51,10 +53,15 @@ func (cli *DockerCli) CmdInspect(args ...string) error {
|
| 51 | 51 |
status := 0 |
| 52 | 52 |
isImage := false |
| 53 | 53 |
|
| 54 |
+ v := url.Values{}
|
|
| 55 |
+ if *size {
|
|
| 56 |
+ v.Set("size", "1")
|
|
| 57 |
+ } |
|
| 58 |
+ |
|
| 54 | 59 |
for _, name := range cmd.Args() {
|
| 55 | 60 |
|
| 56 | 61 |
if *inspectType == "" || *inspectType == "container" {
|
| 57 |
- obj, _, err = readBody(cli.call("GET", "/containers/"+name+"/json", nil, nil))
|
|
| 62 |
+ obj, _, err = readBody(cli.call("GET", "/containers/"+name+"/json?"+v.Encode(), nil, nil))
|
|
| 58 | 63 |
if err != nil && *inspectType == "container" {
|
| 59 | 64 |
if strings.Contains(err.Error(), "No such") {
|
| 60 | 65 |
fmt.Fprintf(cli.err, "Error: No such container: %s\n", name) |
| ... | ... |
@@ -10,6 +10,7 @@ import ( |
| 10 | 10 |
|
| 11 | 11 |
// getContainersByName inspects containers configuration and serializes it as json. |
| 12 | 12 |
func (s *router) getContainersByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
| 13 |
+ displaySize := httputils.BoolValue(r, "size") |
|
| 13 | 14 |
if vars == nil {
|
| 14 | 15 |
return fmt.Errorf("Missing parameter")
|
| 15 | 16 |
} |
| ... | ... |
@@ -25,7 +26,7 @@ func (s *router) getContainersByName(ctx context.Context, w http.ResponseWriter, |
| 25 | 25 |
case version.Equal("1.20"):
|
| 26 | 26 |
json, err = s.daemon.ContainerInspect120(vars["name"]) |
| 27 | 27 |
default: |
| 28 |
- json, err = s.daemon.ContainerInspect(vars["name"]) |
|
| 28 |
+ json, err = s.daemon.ContainerInspect(vars["name"], displaySize) |
|
| 29 | 29 |
} |
| 30 | 30 |
|
| 31 | 31 |
if err != nil {
|
| ... | ... |
@@ -269,6 +269,8 @@ type ContainerJSONBase struct {
|
| 269 | 269 |
ExecIDs []string |
| 270 | 270 |
HostConfig *runconfig.HostConfig |
| 271 | 271 |
GraphDriver GraphDriverData |
| 272 |
+ SizeRw *int64 `json:",omitempty"` |
|
| 273 |
+ SizeRootFs *int64 `json:",omitempty"` |
|
| 272 | 274 |
} |
| 273 | 275 |
|
| 274 | 276 |
// ContainerJSON is newly used struct along with MountPoint |
| ... | ... |
@@ -207,6 +207,7 @@ complete -c docker -f -n '__fish_docker_no_subcommand' -a info -d 'Display syste |
| 207 | 207 |
complete -c docker -f -n '__fish_docker_no_subcommand' -a inspect -d 'Return low-level information on a container or image' |
| 208 | 208 |
complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -s f -l format -d 'Format the output using the given go template.' |
| 209 | 209 |
complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -l help -d 'Print usage' |
| 210 |
+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.' |
|
| 210 | 211 |
complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -a '(__fish_print_docker_images)' -d "Image" |
| 211 | 212 |
complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -a '(__fish_print_docker_containers all)' -d "Container" |
| 212 | 213 |
|
| ... | ... |
@@ -650,6 +650,7 @@ __docker_subcommand() {
|
| 650 | 650 |
_arguments \ |
| 651 | 651 |
$opts_help \ |
| 652 | 652 |
"($help -f --format=-)"{-f,--format=-}"[Format the output using the given go template]:template: " \
|
| 653 |
+ "($help -s --size)"{-s,--size}"[Display total file sizes if the type is container]" \
|
|
| 653 | 654 |
"($help)--type=-[Return JSON for specified type]:type:(image container)" \ |
| 654 | 655 |
"($help -)*: :->values" && ret=0 |
| 655 | 656 |
|
| ... | ... |
@@ -11,7 +11,7 @@ import ( |
| 11 | 11 |
// ContainerInspect returns low-level information about a |
| 12 | 12 |
// container. Returns an error if the container cannot be found, or if |
| 13 | 13 |
// there is an error getting the data. |
| 14 |
-func (daemon *Daemon) ContainerInspect(name string) (*types.ContainerJSON, error) {
|
|
| 14 |
+func (daemon *Daemon) ContainerInspect(name string, size bool) (*types.ContainerJSON, error) {
|
|
| 15 | 15 |
container, err := daemon.Get(name) |
| 16 | 16 |
if err != nil {
|
| 17 | 17 |
return nil, err |
| ... | ... |
@@ -20,7 +20,7 @@ func (daemon *Daemon) ContainerInspect(name string) (*types.ContainerJSON, error |
| 20 | 20 |
container.Lock() |
| 21 | 21 |
defer container.Unlock() |
| 22 | 22 |
|
| 23 |
- base, err := daemon.getInspectData(container) |
|
| 23 |
+ base, err := daemon.getInspectData(container, size) |
|
| 24 | 24 |
if err != nil {
|
| 25 | 25 |
return nil, err |
| 26 | 26 |
} |
| ... | ... |
@@ -40,7 +40,7 @@ func (daemon *Daemon) ContainerInspect120(name string) (*v1p20.ContainerJSON, er |
| 40 | 40 |
container.Lock() |
| 41 | 41 |
defer container.Unlock() |
| 42 | 42 |
|
| 43 |
- base, err := daemon.getInspectData(container) |
|
| 43 |
+ base, err := daemon.getInspectData(container, false) |
|
| 44 | 44 |
if err != nil {
|
| 45 | 45 |
return nil, err |
| 46 | 46 |
} |
| ... | ... |
@@ -54,7 +54,7 @@ func (daemon *Daemon) ContainerInspect120(name string) (*v1p20.ContainerJSON, er |
| 54 | 54 |
return &v1p20.ContainerJSON{base, mountPoints, config}, nil
|
| 55 | 55 |
} |
| 56 | 56 |
|
| 57 |
-func (daemon *Daemon) getInspectData(container *Container) (*types.ContainerJSONBase, error) {
|
|
| 57 |
+func (daemon *Daemon) getInspectData(container *Container, size bool) (*types.ContainerJSONBase, error) {
|
|
| 58 | 58 |
// make a copy to play with |
| 59 | 59 |
hostConfig := *container.hostConfig |
| 60 | 60 |
|
| ... | ... |
@@ -106,6 +106,16 @@ func (daemon *Daemon) getInspectData(container *Container) (*types.ContainerJSON |
| 106 | 106 |
HostConfig: &hostConfig, |
| 107 | 107 |
} |
| 108 | 108 |
|
| 109 |
+ var ( |
|
| 110 |
+ sizeRw int64 |
|
| 111 |
+ sizeRootFs int64 |
|
| 112 |
+ ) |
|
| 113 |
+ if size {
|
|
| 114 |
+ sizeRw, sizeRootFs = container.getSize() |
|
| 115 |
+ contJSONBase.SizeRw = &sizeRw |
|
| 116 |
+ contJSONBase.SizeRootFs = &sizeRootFs |
|
| 117 |
+ } |
|
| 118 |
+ |
|
| 109 | 119 |
// Now set any platform-specific fields |
| 110 | 120 |
contJSONBase = setPlatformSpecificContainerFields(container, contJSONBase) |
| 111 | 121 |
|
| ... | ... |
@@ -27,7 +27,7 @@ func (daemon *Daemon) ContainerInspectPre120(name string) (*v1p19.ContainerJSON, |
| 27 | 27 |
container.Lock() |
| 28 | 28 |
defer container.Unlock() |
| 29 | 29 |
|
| 30 |
- base, err := daemon.getInspectData(container) |
|
| 30 |
+ base, err := daemon.getInspectData(container, false) |
|
| 31 | 31 |
if err != nil {
|
| 32 | 32 |
return nil, err |
| 33 | 33 |
} |
| ... | ... |
@@ -13,5 +13,5 @@ func addMountPoints(container *Container) []types.MountPoint {
|
| 13 | 13 |
|
| 14 | 14 |
// ContainerInspectPre120 get containers for pre 1.20 APIs. |
| 15 | 15 |
func (daemon *Daemon) ContainerInspectPre120(name string) (*types.ContainerJSON, error) {
|
| 16 |
- return daemon.ContainerInspect(name) |
|
| 16 |
+ return daemon.ContainerInspect(name, false) |
|
| 17 | 17 |
} |
| ... | ... |
@@ -109,6 +109,7 @@ list of DNS options to be used in the container. |
| 109 | 109 |
* `GET /info` now lists engine version information. |
| 110 | 110 |
* `GET /containers/json` will return `ImageID` of the image used by container. |
| 111 | 111 |
* `POST /exec/(name)/start` will now return an HTTP 409 when the container is either stopped or paused. |
| 112 |
+* `GET /containers/(name)/json` now accepts a `size` parameter. Setting this parameter to '1' returns container size information in the `SizeRw` and `SizeRootFs` fields. |
|
| 112 | 113 |
|
| 113 | 114 |
### v1.20 API changes |
| 114 | 115 |
|
| ... | ... |
@@ -467,6 +467,26 @@ Return low-level information on the container `id` |
| 467 | 467 |
] |
| 468 | 468 |
} |
| 469 | 469 |
|
| 470 |
+**Example request, with size information**: |
|
| 471 |
+ |
|
| 472 |
+ GET /containers/4fa6e0f0c678/json?size=1 HTTP/1.1 |
|
| 473 |
+ |
|
| 474 |
+**Example response, with size information**: |
|
| 475 |
+ |
|
| 476 |
+ HTTP/1.1 200 OK |
|
| 477 |
+ Content-Type: application/json |
|
| 478 |
+ |
|
| 479 |
+ {
|
|
| 480 |
+ .... |
|
| 481 |
+ "SizeRw": 0, |
|
| 482 |
+ "SizeRootFs": 972, |
|
| 483 |
+ .... |
|
| 484 |
+ } |
|
| 485 |
+ |
|
| 486 |
+Query Parameters: |
|
| 487 |
+ |
|
| 488 |
+- **size** – 1/True/true or 0/False/false, return container size information. Default is `false`. |
|
| 489 |
+ |
|
| 470 | 490 |
Status Codes: |
| 471 | 491 |
|
| 472 | 492 |
- **200** – no error |
| ... | ... |
@@ -18,6 +18,7 @@ parent = "smn_cli" |
| 18 | 18 |
--help=false Print usage |
| 19 | 19 |
--type=container|image Return JSON for specified type, permissible |
| 20 | 20 |
values are "image" or "container" |
| 21 |
+ -s, --size=false Display total file sizes if the type is container |
|
| 21 | 22 |
|
| 22 | 23 |
By default, this will render all results in a JSON array. If a format is |
| 23 | 24 |
specified, the given template will be executed for each result. |
| ... | ... |
@@ -345,3 +345,43 @@ func (s *DockerSuite) TestInspectLogConfigNoType(c *check.C) {
|
| 345 | 345 |
c.Assert(logConfig.Type, check.Equals, "json-file") |
| 346 | 346 |
c.Assert(logConfig.Config["max-file"], check.Equals, "42", check.Commentf("%v", logConfig))
|
| 347 | 347 |
} |
| 348 |
+ |
|
| 349 |
+func (s *DockerSuite) TestInspectNoSizeFlagContainer(c *check.C) {
|
|
| 350 |
+ |
|
| 351 |
+ //Both the container and image are named busybox. docker inspect will fetch container |
|
| 352 |
+ //JSON SizeRw and SizeRootFs field. If there is no flag --size/-s, there are no size fields. |
|
| 353 |
+ |
|
| 354 |
+ dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "top") |
|
| 355 |
+ |
|
| 356 |
+ formatStr := fmt.Sprintf("--format='{{.SizeRw}},{{.SizeRootFs}}'")
|
|
| 357 |
+ out, _ := dockerCmd(c, "inspect", "--type=container", formatStr, "busybox") |
|
| 358 |
+ c.Assert(strings.TrimSpace(out), check.Equals, "<nil>,<nil>", check.Commentf("Exepcted not to display size info: %s", out))
|
|
| 359 |
+} |
|
| 360 |
+ |
|
| 361 |
+func (s *DockerSuite) TestInspectSizeFlagContainer(c *check.C) {
|
|
| 362 |
+ |
|
| 363 |
+ //Both the container and image are named busybox. docker inspect will fetch container |
|
| 364 |
+ //JSON SizeRw and SizeRootFs field. If there is a flag --size/-s, the fields are not <no value>. |
|
| 365 |
+ |
|
| 366 |
+ dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "top") |
|
| 367 |
+ |
|
| 368 |
+ formatStr := fmt.Sprintf("--format='{{.SizeRw}},{{.SizeRootFs}}'")
|
|
| 369 |
+ out, _ := dockerCmd(c, "inspect", "-s", "--type=container", formatStr, "busybox") |
|
| 370 |
+ sz := strings.Split(out, ",") |
|
| 371 |
+ |
|
| 372 |
+ c.Assert(strings.TrimSpace(sz[0]), check.Not(check.Equals), "<nil>") |
|
| 373 |
+ c.Assert(strings.TrimSpace(sz[1]), check.Not(check.Equals), "<nil>") |
|
| 374 |
+} |
|
| 375 |
+ |
|
| 376 |
+func (s *DockerSuite) TestInspectSizeFlagImage(c *check.C) {
|
|
| 377 |
+ |
|
| 378 |
+ //Both the container and image are named busybox. docker inspect will fetch image |
|
| 379 |
+ //JSON SizeRw and SizeRootFs field. There are no these fields since they are only in containers. |
|
| 380 |
+ |
|
| 381 |
+ dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "top") |
|
| 382 |
+ |
|
| 383 |
+ formatStr := fmt.Sprintf("--format='{{.SizeRw}},{{.SizeRootFs}}'")
|
|
| 384 |
+ out, _ := dockerCmd(c, "inspect", "-s", "--type=image", formatStr, "busybox") |
|
| 385 |
+ |
|
| 386 |
+ c.Assert(strings.TrimSpace(out), check.Equals, "<no value>,<no value>", check.Commentf("Fields SizeRw and SizeRootFs are not exepcted to exist"))
|
|
| 387 |
+} |
| ... | ... |
@@ -8,6 +8,7 @@ docker-inspect - Return low-level information on a container or image |
| 8 | 8 |
**docker inspect** |
| 9 | 9 |
[**--help**] |
| 10 | 10 |
[**-f**|**--format**[=*FORMAT*]] |
| 11 |
+[**-s**|**--size**[=*false*]] |
|
| 11 | 12 |
[**--type**=*container*|*image*] |
| 12 | 13 |
CONTAINER|IMAGE [CONTAINER|IMAGE...] |
| 13 | 14 |
|
| ... | ... |
@@ -25,6 +26,9 @@ each result. |
| 25 | 25 |
**-f**, **--format**="" |
| 26 | 26 |
Format the output using the given Go template. |
| 27 | 27 |
|
| 28 |
+**-s**, **--size**=false |
|
| 29 |
+ Display total file sizes if the type is container. |
|
| 30 |
+ |
|
| 28 | 31 |
**--type**=*container*|*image* |
| 29 | 32 |
Return JSON for specified type, permissible values are "image" or "container" |
| 30 | 33 |
|
| ... | ... |
@@ -205,6 +209,18 @@ output: |
| 205 | 205 |
You can get more information about how to write a Go template from: |
| 206 | 206 |
https://golang.org/pkg/text/template/. |
| 207 | 207 |
|
| 208 |
+## Getting size information on an container |
|
| 209 |
+ |
|
| 210 |
+ $ docker inspect -s d2cc496561d6 |
|
| 211 |
+ [ |
|
| 212 |
+ {
|
|
| 213 |
+ .... |
|
| 214 |
+ "SizeRw": 0, |
|
| 215 |
+ "SizeRootFs": 972, |
|
| 216 |
+ .... |
|
| 217 |
+ } |
|
| 218 |
+ ] |
|
| 219 |
+ |
|
| 208 | 220 |
## Getting information on an image |
| 209 | 221 |
|
| 210 | 222 |
Use an image's ID or name (e.g., repository/name[:tag]) to get information |