Introduction
Reducing the size of Docker images helps speed up container deployment. For large-scale deployments, this may result in significant storage space savings. Multiple image optimization methods exist depending on the use case, including using a lightweight base and avoiding unnecessary image layers.
This article will introduce the recommended methods for keeping Docker image size small.
How to Check Docker Image Size
The Docker CLI allows users to check the size of the locally available images. Use the following command to display the basic image information:
docker images
Find the size of images on the list by referring to the SIZE column.
How to Check the Size of Docker Image Layers
A Docker image comprises one or more read-only layers representing file system changes. The layers are stacked on each other, and the sum of their sizes represents the total size of the Docker image.
To list all the layers of an image, use the following docker history
command:
docker history [image]
The output lists image layers in the reverse order of creation, i.e., from newest to oldest. The SIZE column shows the size of each layer.
What Is Docker Image Size Limit?
Docker does not impose a size limit on images, but the maximum size of an image layer is 10 GB. This limitation means that, for example, a 50 GB Docker image must consist of at least five layers.
While users can theoretically create Docker images of any size, image repositories have size limitations for hosting. The most popular public Docker repository, Docker Hub, limits the image size to 100 GB.
How to Set Docker Image Size Limit
A native way to set an image size limit does not exist in Docker. However, the following are two ways to achieve a similar result using third-party tools:
- Utilize CI/CD pipelines. Integrate tools such as Docker Slim and Docker Image Size to perform static and dynamic analyses of Docker images and automatically generate smaller images.
- Set up notifications. Write a bash script that parses the output of the
docker events
command. Then, set up an image size threshold that triggers sending a notification. Optionally, automate the script by setting up a cronjob.
What Is the Recommended Docker Image Size?
There is no universal recommendation for the Docker image size since the structure of an image depends on the context in which the image is produced. The following diagram shows the recommended image sizes for popular Docker usage scenarios.
The list below explains each usage scenario:
- Local development. Developing locally often requires larger images, so images of up to 1 GB are optimal for environments that do not depend on remote repositories.
- Production deployment. Once the image reaches the production deployment phase, optimizing it for resource usage and speed is essential. The aim at this stage is to have an image that is less than 500 MB in size.
- Microservices. Since microservices work best when they are lightweight and easy to scale, each service image should be less than 200 MB.
- Data processing. Images related to data processing and analytics should aim for 500 MB or less. However, the image size can reach 1 GB depending on the tools and libraries utilized.
- Web applications. Web-based apps require containers based on lightweight images that ensure smooth performance. Images less than 500 MB are recommended for the web server, app runtimes, and dependencies.
- IoT and edge. Due to resource constraints, IoT and edge images must be minimal. An optimal IoT image should be less than 100 MB.
How to Reduce Docker Image Size
Techniques for reducing Docker image size to the minimum include choosing the right base image and excluding unnecessary files and layers. The following sections contain tips for minimizing Docker images while retaining the necessary data.
Use Slim Image Base
Each Docker image needs a base on which further components can be added. The image creator adds an existing parent image using the Dockerfile FROM
call.
The base of an image is often an entire operating system, which can drastically impact the size of the final Docker image. For example, the most popular OS image, Ubuntu, takes up more than 150 MB, which creates a significant overhead at the beginning of the image creation process.
A helpful lightweight alternative is Alpine, a minimal POSIX environment. This Linux distribution image base is only 5 MB and is built around musl libc and BusyBox.
Create .dockerignore
Use a .dockerignore file to exclude files unnecessary for the final image build. When the docker run
command is executed, Docker checks if a .dockerignore file is present in the project directory and, if it is, creates an image container that excludes the files and directories listed in it.
The .dockerignore file has a simple syntax. For example, to exclude the text file test.txt and all MD files except for readme.md, create a .dockerignore with the following content:
test.txt
*.md
!readme.md
Note: Remember to place .dockerignore in the same directory as the Dockerfile.
Utilize Multi-Stage Builds
Docker's multi-stage feature allows users to divide the Dockerfile into multiple stages. Each stage begins with a FROM
call and passes the required artifact to the following stage. This procedure eliminates all the unnecessary content before the final image artifact is created.
Since the multi-stage builds only transfer the necessary components of the artifact, users do not have to clean up manually after every call. The process allows users to separate build-time dependencies from runtime dependencies and eliminates the need to create additional layers.
Avoid Unnecessary Layers
A Docker image requires more space with every added layer. Since each RUN
instruction in a Dockerfile adds a new layer to the image, the best practice is to fit as much as possible within a single RUN
command. Furthermore, the &&
shell feature can combine different commands into one instruction.
For instance, to update the repository, install multiple packages, and clean up the APT cache in a single RUN
instruction, use the following command:
RUN apt update &&\
apt install -y\
[package1] \
[package2] &&\
rm -rf /var/lib/apt/lists/*
Use the backslash (\) to type the command in multiple lines and make it more readable.
Remove Unnecessary Packages and Dependencies
Installing a package often includes downloading dependencies. However, the download process sometimes also stores optional packages.
Such unwanted packages can add up and consume a lot of disk space. Add the --no-install-recommends
option to the install command to download only the main dependencies:
RUN apt install --no-install-recommends [package]
Organize Layers for Caching
Docker speeds up image building by locally caching existing layers of a Dockerfile and using the cache to rebuild images faster. However, the cache is used only for the layers preceding the modified layer.
To optimize your image, place Dockerfile instructions that are likely to change as low in the Dockerfile as possible so that they are executed last. While this practice does not affect the overall size of the Docker image, it still helps speed up Docker builds.
Conclusion
After reading this article, you should know how to optimize your Docker images and keep them small to improve your application's performance. Image size and build efficiency are essential factors when overseeing and working with containers.
Next, read how to further optimize Docker performance.