How to make Docker images smaller
Github: nturaga; Twitter: niteshturaga
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.
- AUFS is a union filesystem.
- 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
- The website, fromlatest.io (https://www.fromlatest.io/#/), allows you to paste your
Dockerfile
and it’ll point at optimization locations in theDockerfile
for you. - 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.
- Consider using a
--no-install-recommends
whenapt-get
installing packages. This will result in a smaller image size. - Consider using
rm -rf /var/lib/apt/lists/*
to every line you do anapt-get update
or at least once at the end of your Dockerfile.