Keep it Small : tips for optimising docker images for a faster development workflow
“The Smaller the better !”
Docker is now a key part of the release lifecycle in almost all organisations . Developers like working with Docker for its flexibility and ease-of-use. When creating applications, it’s worth investing the extra time in optimising Docker Images and Docker files.
Does Docker Size Really matters ?
Does Docker image size matter? The answer usually is “yes”.
The logical question that follows is “Why?”, and a follow up question comes “How?”
Let’s check “Why”
Security
Generally, using smaller container images comes with a lesser number of libraries inside. This reduces the attack surface to the container. In addition, when we are building images using this approach, we are more transparent whats happening inside.
Performance and Efficiency
Smaller containers, makes them moving much easier and faster. This improves the performance of the build and deployment processes since less container image data needs to be pulled to the running container cluster. They also are efficient on disk size and memory as well .
Maintainability
Since there are less dependencies and libraries installed, it also simplifies managing these libraries, keeping them up to date with operating system patches and etc.
Container size affects application life-cycle in many aspects. Making them small improves these containers in security, performance, efficiency, and maintainability of a containerized application. Although making the container sizes small is not a must, at least trying to build the application container using a minimal base image like Alpine greatly helps in understanding the details of individual container dependencies.
Now let’s check “How?”
Tip #1 :- Have a lighter ( Smaller ) Base Image
Using an appropriate base image for your project can make a huge difference. It makes sense to use the official Ruby image for your Rails project, but if you’re just executing a binary in a container, do you need the full Ubuntu image? Maybe you can use a smaller image, like Alpine, or even just run a Scratch container?
FROM ubuntu
will set you to 128MB on the outset. Consider using a smaller base image. For each apt-get installor yum install line you add in your Dockerfile ,you will be increasing the size of the image by that library size. Realize that you probably don’t need many of those libraries you are installing.
Consider using an alpine base image (only 5MB in size). Most likely, there are alpine tags for the programming language you are using. For example, Python has 2.7-alpine(~50MB) and3.5-alpine(~65MB).
Compare the above Busybox’s size that to Ubuntu’s size and you can see how making this one change alone is a significant saving. To make it easier, here’s an image size comparison:
Tip #2 :- Don’t install debug tools like vim/curl
Many developers install vim and curl in their Dockerfile so that they can more easily debug their application. Unless your application depends on it, don’t install those dependencies. Doing so defeats the purpose of using a small base image.
But how do one debug?
One technique is to have a development Dockerfile and a production Dockerfile. During development, have all of the tools you need, and then when deploying to production remove the development tools.
Tip #3 :- Minimize Dockerfile Lines ( Minimize Layers)
Each line of a Dockerfile is a step in the build process; a layer that takes up size. Combine your RUN statements to reduce the image size. Instead of
FROM debian
RUN apt-get install -y <packageA>
RUN apt-get install -y <packageB>
Do
FROM debian
RUN apt-get install -y <packageA> <packageB>
A drawback of this approach is that you’ll have to rebuild the entire image each time you add a new library.
If you aren’t aware, Docker doesn’t rebuild layers it’s already built, and it caches the Dockerfile line by line , try changing one character of a Dockerfile you’ve already built, and then rebuild. You’ll notice that each step above that line will be recognized as already been built, but the line you changed (and each line following) will be rebuilt.
Tip #4 :- Use no-install-recommends on apt-get install
Adding — no-install-recommends
to apt-get install -y
can help dramatically reduce the size by avoiding installing packages that aren’t technically dependencies but are recommended to be installed alongside packages.
apk add
commands should have--no-cache
added.
Tip #5 :- Use no-install-recommends on apt-get install to clean install packages
Add rm -rf /var/lib/apt/lists/*
at the end of the apt-get -y install
to clean up after install packages.
For yum
, add yum clean all
Also, if you are install wget
or curl
in order to download some package, remember to combine them all in one RUN
statement. Then at the end of the run statement, apt-get remove curl
or wget
once you no longer need them. This advice goes for any package that you only need temporarily.
Tip #6 :- Squash Docker Images
Squash Docker images. The idea here is that after your image is created, you then flatten it as much as possible, using a tool such as docker-squash.
Docker-squash is a utility to squash multiple docker layers into one to create an image with fewer and smaller layers. It retains Dockerfile commands such as PORT, ENV, etc.. so that squashed images work the same as they were originally built. In addition, deleted files in later layers are actually purged from the image when squashed.
Tip #7 :- Squash Docker Images
FromLatest will Lint your Dockerfile and check for even more steps you can perform to reduce your image size.
Tip #8 :- Use .dockerignore files
These files, as their name implies, instruct Docker that specific files can be ignored just like .gitignore does .
If unfamiliar with .gitignore concept , then have a look at below example
vendor
.idea
data
mysql
Using this configuration Docker would not copy any files in the vendor, .idea, data, or mysql directories of the project, saving both time and space in the process. .dockerignore files are convenient.
There are many other tips out there to decrease Docker Image size . Feel free to share any if that is missed here .