DEV Community

Cover image for Docker Image Optimization: Reducing Size for Faster Deployments

Docker Image Optimization: Reducing Size for Faster Deployments

Dhananjay Patel on November 16, 2024

Introduction A few months ago, while working on a critical deployment for a client, we faced an unexpected issue: the deployment took fo...
Collapse
 
simongreennet profile image
Simon Green • Edited

You said moving from ubuntu:latest to alpine:latest "reduced the image size from 800MB to less than 30MB". The current version of Ubuntu (sha fec8bfd95b54) is only 78 MB, and Alpine is 7.8 MB. I think there would have had to be other changes to have such a reduction.

In the forth point builtkit supports heredocs. Rather than endless && \ statements this would be more readable, especially for more complex runs.

RUN <<EOF
apt-get update
apt-get install -y curl vim
apt-get clean
rm -rf /var/lib/apt/lists/
EOF
Enter fullscreen mode Exit fullscreen mode
Collapse
 
swastikgorai profile image
S.Go

I'd suggest one to use a somewhat bigger base image in build phase, then use alpine or slim in application phase and move the deps to it. Cuz afaik and have had experience, directly using a small image at the beginning may cause some installation of deps to fail.

Collapse
 
thenanjay profile image
Dhananjay Patel

Thank you for sharing your insight! You’re absolutely right—starting with a slightly larger base image in the build phase can help avoid issues with dependency installations, especially when using minimal images like Alpine. Transitioning to a smaller image (like Alpine or a slim variant) in the runtime phase is indeed a smart way to balance compatibility and optimization.

For Node.js projects specifically, using the node image directly in the build phase is a great option since it comes pre-configured for most setups. Similarly, other tech stacks might benefit from base images tailored to their needs during the build phase.

Collapse
 
gaswigue profile image
Gaswigue

Using not alpine for dependency installation can install incompatible lib version for alpine.
Alpine use musl libc vs glibc for other base.
Another point, bumping your package.json version will invalidate the docker cache layer.
There is some technic to avoid this, like, using a temporary step setting the package.json to version 1.0 for instance before install.

Collapse
 
thenanjay profile image
Dhananjay Patel

Thank you for diving into these technical details—great points!

You’re absolutely correct about the musl libc vs. glibc difference. Alpine’s musl libc can indeed cause compatibility issues with some libraries, which is why choosing the right base image for dependency installation is crucial. This is also why multi-stage builds work so well—dependencies can be built in a compatible environment (glibc-based) and then moved to a smaller runtime image like Alpine if desired.

The point about package.json is spot on as well. When the version changes, it invalidates the Docker cache, which can significantly increase build times. I really like the technique you mentioned, where a temporary package.json with a static version is used during installation—it’s a clever way to maintain cache efficiency.

Collapse
 
danlee1996 profile image
Daniel Lee

Good article.

Will try to implement some of these techniques at my workplace.

Collapse
 
thenanjay profile image
Dhananjay Patel

Thank you! Glad you found it helpful—let me know how it works out for you! 🚀

Collapse
 
kristiyan_velkov profile image
Kristiyan Velkov

FROM alpine:latest - you should specify the exact version of the alpine image if you don;t wont to have a problems in the future.

Collapse
 
thenanjay profile image
Dhananjay Patel

You’re absolutely right! Using alpine:latest can lead to unexpected issues if the base image changes, so specifying an exact version is a best practice for production.

However, in multi-stage builds, using latest for the build stage can sometimes be beneficial to leverage the latest tools and updates.

so it depends :)

Collapse
 
kurealnum profile image
Oscar

Multi-stage builds are also awesome for optimizing Docker stuff: docs.docker.com/build/building/mul...

Collapse
 
ashwingopalsamy profile image
Ashwin Gopalsamy

Useful. Thanks.

Collapse
 
afser_61b2f18859 profile image
Muhammed Afser

Article does a great job in listing the best practices while building docker images. Article is neat and precise. Keep up the great work.

Collapse
 
thenanjay profile image
Dhananjay Patel

Thank you so much for the encouraging words! 😊 I'm glad you found the article helpful. Stay tuned for more content like this!

Collapse
 
surya_f8c6194ccabac1c4a88 profile image
Surya

Very helpful my trainer didn't teach me about these he skipped whatever thanks bro

Collapse
 
thenanjay profile image
Dhananjay Patel

Glad you found it helpful! Sometimes trainers skip over these finer details, but exploring them yourself makes the learning even more rewarding. Happy optimizing, bro! 🚀

Collapse
 
coder_dragon profile image
Shivam

Using cache can also speed up your build process.

Collapse
 
thenanjay profile image
Dhananjay Patel

Great point! I’ve actually written a blog on using Docker layer caching to speed up builds—check it out here: link 😊

Collapse
 
luojiyin1987 profile image
luo jiyin

docker-slim is not a good tool, It's very rough. It can't tell what's useful and what's not. It only knows to delete . It lacks maintenance.

Collapse
 
thenanjay profile image
Dhananjay Patel

Thanks for pointing that out! It’s true that tools like Docker Slim have limitations and aren’t a fit for all scenarios. I’ll explore other options and see what else can be used for better optimization.

Collapse
 
vijaym_gowda_88673ef1795 profile image
vijay.m Gowda • Edited

Wonderfu artical .. well, I have question.. will docker slim is reduces image vulnerabilities for open source images ?

Collapse
 
thenanjay profile image
Dhananjay Patel

Thank you for the kind words! 😊

As for your question: docker-slim does help in reducing image vulnerabilities to some extent. By removing unnecessary files, libraries, and binaries, it reduces the image’s attack surface. However, it’s important to note that it doesn’t directly fix known vulnerabilities in dependencies. For that, tools like Trivy or Snyk are super helpful to scan and address those issues.

Using docker-slim alongside regular vulnerability scans is a great combo for both smaller and safer images! 🚀

Collapse
 
bobbyiliev profile image
Bobby Iliev

Cool post! If anyone wants to learn more about Docker I could suggest this free eBook here:

GitHub logo bobbyiliev / introduction-to-docker-ebook

Free Introduction to Docker eBook

💡 Introduction to Docker

This is an open-source introduction to Docker guide that will help you learn the basics of Docker and how to start using containers for your SysOps, DevOps, and Dev projects. No matter if you are a DevOps/SysOps engineer, developer, or just a Linux enthusiast, you will most likely have to use Docker at some point in your career.

The guide is suitable for anyone working as a developer, system administrator, or a DevOps engineer and wants to learn the basics of Docker.

🚀 Download

To download a copy of the ebook use one of the following links:

📘 Chapters

Collapse
 
bassg0navy profile image
bassg0navy

Is anybody actually doing continuous deployment? I’ve worked at a few places but never any where that was the reality or the goal. Curious if anyone here has implemented in a production environment.

Collapse
 
raphaelcarlosr profile image
raphaelcarlosr.dev

All these is in docker init command

Some comments have been hidden by the post's author - find out more