Docker Images : Part III - Going Farther To Reduce Images Size

Docker Images : Part III - Going Farther To Reduce Images Size

Series Index Reducing Image Size Details Specific To Different Languages Going Farther To Reduce Image Size Introduction In the first two parts of this series, we covered the most common methods to optimize Docker image size. We saw how multi-stage builds, combined with Alpine-based images, and sometimes static builds, would generally give us the most dramatic savings. In this last part, we will see how to go even farther. We will talk about standardizing base images, stripping binaries, assets optimization, and other build systems or add-ons like DockerSlim or Bazel, as well as the NixOS distribution.

Introduction

In the first two parts of this series, we covered the most common methods to optimize Docker image size. We saw how multi-stage builds, combined with Alpine-based images, and sometimes static builds, would generally give us the most dramatic savings. In this last part, we will see how to go even farther. We will talk about standardizing base images, stripping binaries, assets optimization, and other build systems or add-ons like DockerSlim or Bazel, as well as the NixOS distribution.

We’ll also talk about small details that we left out earlier, but are important nonetheless, like timezone files and certificates.

Common bases

If our nodes run many containers in parallel (or even just a few), there’s one thing that can also yield significant savings.

Docker images are made of layers. Each layer can add, remove, or change files; just like a commit in a code repository, or a class inheriting from another one. When we execute a docker build,each line of the Dockerfile will generate one layer. When we transfer an image, we only transfer the layers that don’t already exist on the destination.

Layers save network bandwidth, but also storage space: if multiple images share layers, Docker needs to store these layers only once. And depending on the storage driver that you use, layers can also save disk I/O and memory, because when multiple containers need to read the same files from a layer, the system will read and cache these files only once. (This is the case with the overlay2 and aufs drivers.)

This means that if we’re trying to optimize network and disk access, as well as memory usage, in nodes running many containers, we can save a lot by making sure that these containers run images that have as many common layers as possible.

This can directly go against some of the guidelines that we gave before! For instance, if we’re building super optimized images using static binaries, these binaries might be 10x bigger than their dynamic equivalents. Let’s look at a few hypothetical scenarios when running 10 containers, each using a different image with one of these binaries.

Scenario 1: static binaries in a scratch image

  • weight of each image: 10 MB
  • weight of the 10 images: 100 MB

Scenario 2: dynamic binaries with ubuntu image (64 MB)

  • individual weight of each image: 65 MB
  • breakdown of each image: 64 MB for ubuntu + 1 MB for the specific binary
  • total disk usage: 74 MB (10x1 MB for individual layers + 64 MB for shared layers)

Scenario 3: dynamic binaries with alpine image (5.5 MB)

  • individual weight of each image: 6.5 MB
  • breakdown of each image: 5.5 MB for alpine + 1 MB for the specific binary
  • total disk usage: 15.5 MB

These static binaries looked like a good idea at first, but in these circumstances, they are highly counterproductive. The images will require more disk space, take longer to transfer, and use more RAM!

images docker dockerslim nixos bazel

What is Geek Coin

What is GeekCash, Geek Token

Best Visual Studio Code Themes of 2021

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Docker creating an image | Build and run your image | Docker Fundamentals

Docker create an image from a container | Creating your own image | How to create Docker Image from a Container and Dockerfile

Docker manifest - A peek into image's manifest.json files

The docker manifest command does not work independently to perform any action. In order to work with the docker manifest or manifest list, we use sub-commands along with it. This manifest sub-command can enable us to interact with the image manifests. Furthermore, it also gives information about the OS and the architecture, that a particular image was built for. The image manifest provides a configuration and a set of layers for a container image. This is an experimenta

Docker Explained: Docker Architecture | Docker Registries

Following the second video about Docker basics, in this video, I explain Docker architecture and explain the different building blocks of the docker engine; docker client, API, Docker Daemon. I also explain what a docker registry is and I finish the video with a demo explaining and illustrating how to use Docker hub.

Sharing Docker Images on Docker Hub

An image like the one we created in the Node.js Hello World Docker Container from scratch post is simple, yet it’s a perfect example to try one of the cool features of Docker, provided through Docker Hub, the official hosting service of public and private Docker Images. Before we can do that, however, we need to register on Docker Hub. Docker Hub is free in its basic plan which includes unlimited public repos and one private repo.

Removing Docker Images

In a previous article, we explained the difference between Docker images and Docker containers. In short: An image is like a Java class, and containers are like Java objects. In this tutorial, we'll look at the various ways of removing Docker images.