1

For context, I'm trying to compute the total size in bytes taken by docker images on my machine. I know of docker system df, but I want to understand how I can do this in general.

If I run docker image ls -a, I get something like this:

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
debian              8                   00b72214a37e        3 days ago          129MB
debian              latest              971452c94376        3 days ago          114MB

Now I'd like to sum the SIZE column, so I can remove the first row with tail +2, and then use awk to sum the 7th column (using this):

docker image ls -a | tail +2 | awk '{s+=$7}END{print s}'

This command will correctly give me the total size in MB (243MB).

However, if an image has its size in GB, awk will add it to the sum but will ignore the unit, so for instance, the same command would return 244MB instead of 1.243GB on the following images:

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
debian              8                   00b72214a37e        3 days ago          129MB
debian              latest              971452c94376        3 days ago          114MB
debian              latest              971452c94376        3 days ago          1GB

How can I tweak my command to have it support sizes (or values in general) with different metric prefixes? I don't necessarily want the output to be formatted in any way, for instance an output in bytes would be fine.

Right leg
  • 16,080
  • 7
  • 48
  • 81
  • Something like this https://stackoverflow.com/questions/45616580/converting-kb-and-gb-to-mb-in-bash – Tarun Lalwani Mar 16 '21 at 09:55
  • 2
    [Why you shouldn't parse the output of ls\(1\)](https://mywiki.wooledge.org/ParsingLs) shall apply here as well with docker which surely provide an API or command with JSON output that is more appropriate to use in code. – Léa Gris Mar 16 '21 at 10:44
  • @LéaGris Thanks for your link! But as I said, I'd like to understand how I can do this in a general case. Not all CLI programs offer a way to format output to easily manipulate it. Moreover, if you're interested in Docker specifically (which, again, is only the context here), the right way is, as I wrote, [`docker system df`](https://docs.docker.com/engine/reference/commandline/system_df/), which outputs the size of images. – Right leg Mar 16 '21 at 11:18
  • What is `this` in the statement `I'd like to understand how I can do *this* in a general case`? Is `this` sum a few values with different metric suffixes that could represent anything or is `this` get the total size of files in a directory on any Unix box or is `this` something else? – Ed Morton Mar 16 '21 at 14:07
  • @EdMorton It's exactly that, how to sum values with different metric suffixes. It could even be extended to summing values in different non-metric units, like seconds and minutes; although some approaches may solve the former but not the latter. – Right leg Mar 16 '21 at 18:19
  • You already got an answer to how to get file sizes in docker which is what you appeared to some of us to be asking about so you should probably accept that answer to this question and then ask a new question about the more general case with more truly representative and diverse sample input/output about just that specifically and none of the docker/ls specific stuff you have in this question that's apparently irrelevant – Ed Morton Mar 16 '21 at 18:54

1 Answers1

2

You can do this reliably with different docker command in bash using this script:

tot=
while read id; do
   (( tot += $(docker image inspect --format='{{.Size}}' $id) ))
done < <(docker image ls --format='{{.ID}}')

echo "total-size-in-bytes=$tot"

Note that:

  • docker image inspect --format='{{.Size}}' prints size of a given image in bytes
  • docker image ls --format='{{.ID}}' prints all images IDs
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • Thanks, `docker image inspect --format='{{.Size}}'` helped me! It's a bit confusing that this gives the size in bytes whereas `docker image ls` gives it in human-readable format - I'd have expected to have to pass a `-h` flag for that purpose, just like `ls -h`. Anyway, I came up with a monstruosity of pipes, obviously not the right way. If I abstract this answer from Docker, I suppose the general way is to find how to get all the values in the same metric suffix. – Right leg Mar 16 '21 at 11:27
  • Maybe you could combine with a single command: `while IFS=$'\t' read -r id size; do tot+=size; printf '%s\t%d\n' "$id" "$size"; done < <(docker container ls --format '{{.ID}}\t{{.Size}}'\n; printf 'Total size:\t%d\n' "$tot";` – Léa Gris Mar 16 '21 at 11:29
  • 1
    @LéaGris: That `.Size` is not in bytes but in human readable format. – anubhava Mar 16 '21 at 13:39