One day, I was looking for some gains to improve the startup time for Jenkins agents. We run them as containers and because images are quite big, I was thinking about cutting the size, by cutting less frequently used features. I was looking for the metrics I could use to decide which changes are most valuable. I could think about two: download time and startup time. Together they combine to the gap between the request to start agent and the moment you can start to use it. Sadly it wasn’t that easy to measure that and collect statistics. It’s also not that practical, when you’re developing improvement as you can’t see the difference.
I started thinking about alternative metrics and I quickly figured out, that I can check Docker image compressed size. It would be proportional to the download time. I can also compare compressed size with uncompressed size as it will show how much data have to be extracted, being proportional to the startup time. Although those KPIs are not as good, they’re fairy ok to use during development.
Then I found, it’s not that easy to guess compressed size of Docker image. docker image ls
shows extracted size. docker inspect
shows compressed size per layer. Luckily I found1 nice bash function that can make the whole process easy:
dockersize() { docker manifest inspect -v "$1" | jq -c 'if type == "array" then .[] else . end' | jq -r '[ ( .Descriptor.platform | [ .os, .architecture, .variant, ."os.version" ] | del(..|nulls) | join("/") ), ( [ .SchemaV2Manifest.layers[].size ] | add ) ] | join(" ")' | numfmt --to iec --format '%.2f' --field 2 | column -t ; }
Now it’s easy to imagine download time impact and gains from my work:
$ docker pull alpine
$ docker pull python
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
python latest 33039c2f184f 5 weeks ago 1.02GB
alpine latest 1dc785547989 7 weeks ago 7.73MB
$ dockersize alpine
linux/amd64 3.26M
linux/arm/v6 3.02M
linux/arm/v7 2.79M
linux/arm64/v8 3.20M
linux/386 3.10M
linux/ppc64le 3.21M
linux/s390x 3.10M
$ dockersize python
linux/amd64 362.96M
linux/arm/v5 330.63M
linux/arm/v7 316.31M
linux/arm64/v8 353.81M
linux/386 365.13M
linux/ppc64le 377.20M
linux/s390x 333.43M
windows/amd64/10.0.20348.2227 1.83G
windows/amd64/10.0.17763.5329 1.99G