Keep it Small : tips for optimising docker images for a faster development workflow

Tushar Sappal
Tech Bits
Published in
5 min readMay 24, 2019

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:

Docker Image 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-recommendsto 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 .

--

--