How to make Docker images smaller

Trying to make Docker images smaller is a little bit easier if you know how the filesystem works and have a few handy resources.

My first naive effort, I was trying to delete stuff from the top layer of a 5Gb image (with plenty of layers). Once I saved the image, the size was almost exactly the same. Nothing changed. WHAT?

How does the Docker file system work?

Docker works using layers of images. Docker uses one of the two file systems depending on your Linux kernel.

  1. AUFS is a union filesystem.
  2. overlay2.

To find out which one your docker engine is using,

❯❯❯ docker info | grep Storage
Storage Driver: overlay2

If you try just docker info you’ll see plenty of great information which is very useful, including my favorites such as (this is a shorter list)

Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 26
Kernel Version: 4.9.125-linuxkit
Operating System: Docker for Mac
OSType: linux
Architecture: x86_64
CPUs: 2
Total Memory: 7.787GiB
Docker Root Dir: /var/lib/docker

What is overlay2?

Overlay2 (overlayFS) is a modern union filesystem that is similar to AUFS, but faster and with a simpler implementation.

A union filesystem, layers multiple directories on a single Linux host and presents them as a single directory. So, all your layers give the appearance of being unified in the “top” writeable layer of the container. It’s not really all at the top level.

docker history

To know which layers are the largest on your image, (more info on docker history)

docker history <image name>:<tag>

This information is useful to identify which layers exactly are adding to the size of your image. Once you identify the line in either your top level Dockerfile or any of the inherited Dockerfile’s, you can try and fix that specific image where that command is coming from.

Deleting files and directories

When you delete a file or a directory from a container, the reason it does NOTHING to change the size of the layers below is:

  • When a file is deleted within a container, a whiteout file is created in the container layer. The version of the file in the image layer is not deleted (because the image layers are read-only). However, the whiteout file prevents it from being available to the container.
  • When a directory is deleted within a container, an opaque file is created in the container layer. This works in the same way as a whiteout file and effectively prevents the directory from being accessed, even though it still exists in the image layer.

Resources to (potentially) reduce image size

  1. The website, fromlatest.io (https://www.fromlatest.io/#/), allows you to paste your Dockerfile and it’ll point at optimization locations in the Dockerfile for you.
  2. Do not install the same package/library a second time. If the image underneath has it in some layer, it is available to you* (given the right permissions). If you install again, a new layer is added and the size of your image goes up.
  3. Consider using a --no-install-recommends when apt-get installing packages. This will result in a smaller image size.
  4. Consider using rm -rf /var/lib/apt/lists/* to every line you do an apt-get update or at least once at the end of your Dockerfile.

References

  1. https://docs.docker.com/storage/storagedriver/aufs-driver/
  2. https://medium.com/@paccattam/drooling-over-docker-2-understanding-union-file-systems-2e9bf204177c
  3. https://docs.docker.com/engine/reference/commandline/history/

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store