DEV Community

Cover image for Few steps to make your docker image smaller
Anton Sukhachev
Anton Sukhachev

Posted on • Edited on

Few steps to make your docker image smaller

[original post]

I have some projects where I need bison. I decided to build my image when I didn't find official or fresh unofficial docker images.

To compile bison you need to install some apt dependencies and compile the last version of autoconf from the source code.
I decided to make it from debian:bullseye-slim image. It is the latest Debian light image which size is 80.5MB (without compression).

docker images --format="table {{.Repository}}\t{{.Tag}}\t{{ .Size }}"  | grep "REPOSITORY\|debian"
REPOSITORY    TAG             SIZE
debian        bullseye-slim   80.5MB
Enter fullscreen mode Exit fullscreen mode

bison-test:1.0

First I make a simple Dockerfile and build it.

FROM debian:bullseye-slim

ENV BISON_VERSION v3.8.2
ENV AUTOCONF_VERSION 2.71

# install apt dependencies
RUN set -eux; \
    apt-get update; \
    apt-get install -y \
        automake \
        autopoint \
        ca-certificates \
        flex \
        gettext \
        gcc \
        git \
        gperf \
        graphviz \
        help2man \
        libc6-dev \
        m4 \
        make \
        texinfo \
        wget \
        xsltproc

# compile autoconf
RUN wget ftp://ftp.gnu.org/gnu/autoconf/autoconf-$AUTOCONF_VERSION.tar.gz
RUN tar -xvzf autoconf-$AUTOCONF_VERSION.tar.gz
WORKDIR /autoconf-$AUTOCONF_VERSION
RUN ./configure
RUN make
RUN make install
WORKDIR /

# compile bison
RUN git clone --branch=$BISON_VERSION --depth=1 https://github.com/akimd/bison.git /bison
WORKDIR /bison
RUN git submodule update --init --recursive
RUN ./bootstrap
RUN ./configure
RUN make
RUN make install
WORKDIR /
Enter fullscreen mode Exit fullscreen mode
docker build -t bison-test:1.0 .
Enter fullscreen mode Exit fullscreen mode

Ok. Image contains many layers

docker history bison-test:1.0 --format="table {{.CreatedBy }}\t{{ .Size }}" | grep -v 0B
CREATED BY                                      SIZE
RUN /bin/sh -c make install # buildkit          5.86MB
RUN /bin/sh -c make # buildkit                  22.3MB
RUN /bin/sh -c ./configure # buildkit           2.02MB
RUN /bin/sh -c ./bootstrap # buildkit           18.1MB
RUN /bin/sh -c git submodule update --init -…   137MB
RUN /bin/sh -c git clone --branch=$BISON_VER…   6.55MB
RUN /bin/sh -c make install # buildkit          3.46MB
RUN /bin/sh -c make # buildkit                  990kB
RUN /bin/sh -c ./configure # buildkit           127kB
RUN /bin/sh -c tar -xvzf autoconf-$AUTOCONF_…   6.88MB
RUN /bin/sh -c wget ftp://ftp.gnu.org/gnu/au…   2MB
RUN /bin/sh -c set -eux;     apt-get update;…   348MB
/bin/sh -c #(nop) ADD file:3ea7c69e4bfac2ebb…   80.5MB
Enter fullscreen mode Exit fullscreen mode

and the total size is 633MB.

docker images --format="table {{.Repository}}\t{{.Tag}}\t{{ .Size }}"  | grep "REPOSITORY\|bison-test"
REPOSITORY    TAG             SIZE
bison-test    1.0             633MB
Enter fullscreen mode Exit fullscreen mode

bison-test:2.0

Let's reduce layers.
Instead of creating many separate RUN commands, I wrote two scripts.

RUN set -eux; \
   wget ftp://ftp.gnu.org/gnu/autoconf/autoconf-$AUTOCONF_VERSION.tar.gz; \
   tar -xvzf autoconf-$AUTOCONF_VERSION.tar.gz; \
    cd /autoconf-$AUTOCONF_VERSION; \
   ./configure; \
   make; \
   make install

RUN set -eux; \
   git clone --branch=$BISON_VERSION --depth=1 https://github.com/akimd/bison.git /bison; \
   cd /bison; \
   git submodule update --init --recursive; \
   ./bootstrap; \
   ./configure; \
   make; \
   make install
Enter fullscreen mode Exit fullscreen mode

The number of layers has decreased

docker history bison-test:2.0 --format="table {{.CreatedBy }}\t{{ .Size }}" | grep -v 0B
CREATED BY                                      SIZE
RUN /bin/sh -c set -eux;  git clone --branch…   188MB
RUN /bin/sh -c set -eux;  wget ftp://ftp.gnu…   13.5MB
RUN /bin/sh -c set -eux;     apt-get update;…   348MB
/bin/sh -c #(nop) ADD file:3ea7c69e4bfac2ebb…   80.5MB
Enter fullscreen mode Exit fullscreen mode

but the total size is only 3 MB smaller.

docker images --format="table {{.Repository}}\t{{.Tag}}\t{{ .Size }}"  | grep "REPOSITORY\|bison-test"
REPOSITORY    TAG             SIZE
bison-test    2.0             630MB
Enter fullscreen mode Exit fullscreen mode

bison-test:3.0

Now I'll try to remove all the source files and add another RUN command to remove the apt dependencies and the apt cache.

RUN set -eux; \
   wget ftp://ftp.gnu.org/gnu/autoconf/autoconf-$AUTOCONF_VERSION.tar.gz; \
   tar -xvzf autoconf-$AUTOCONF_VERSION.tar.gz; \
    cd /autoconf-$AUTOCONF_VERSION; \
   ./configure; \
   make; \
   make install; \
   rm -rf /autoconf-$AUTOCONF_VERSION.tar.gz; \ # remove unnecessary source files
    rm -rf /autoconf-$AUTOCONF_VERSION # remove unnecessary source files

RUN set -eux; \
   git clone --branch=$BISON_VERSION --depth=1 https://github.com/akimd/bison.git /bison; \
   cd /bison; \
   git submodule update --init --recursive; \
   ./bootstrap; \
   ./configure; \
   make; \
   make install; \
   rm -rf /bison # remove unnecessary source files

# remove apt dependencies and cache
RUN set -eux; \
    apt-mark auto '.*' > /dev/null; \
    apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
    rm -rf /var/lib/apt/lists/*
Enter fullscreen mode Exit fullscreen mode
docker history bison-test:3.0 --format="table {{.CreatedBy }}\t{{ .Size }}" | grep -v 0B
CREATED BY                                      SIZE
RUN /bin/sh -c set -eux;     apt-mark auto '…   1.96MB
RUN /bin/sh -c set -eux;  git clone --branch…   5.83MB
RUN /bin/sh -c set -eux;  wget ftp://ftp.gnu…   3.46MB
RUN /bin/sh -c set -eux;     apt-get update;…   330MB
/bin/sh -c #(nop) ADD file:3ea7c69e4bfac2ebb…   80.5MB
Enter fullscreen mode Exit fullscreen mode

The total size is 422MB. It's 211MB smaller than the first image bison-test:1.0

docker images --format="table {{.Repository}}\t{{.Tag}}\t{{ .Size }}"  | grep "REPOSITORY\|bison-test"
REPOSITORY    TAG             SIZE
bison-test    3.0             422MB
Enter fullscreen mode Exit fullscreen mode

bison-test:4.0

The last image is smaller, but too large compared to the original debian:bullseye-slim image.
When you see the previous image layers, you may notice that the apt-install layer is very big and the last command does not reduce the size of the image.
I need to install dependencies, compile bison and remove dependencies inside one layer.
Let's do it.

FROM debian:bullseye-slim

ENV BISON_VERSION v3.8.2
ENV AUTOCONF_VERSION 2.71

RUN set -eux; \
    apt-get update; \
    apt-get install -y --no-install-recommends \
        automake \
        autopoint \
        ca-certificates \
        flex \
        gettext \
        gcc \
        git \
        gperf \
        graphviz \
        help2man \
        libc6-dev \
        m4 \
        make \
        texinfo \
        wget \
        xsltproc; \
    \
   wget ftp://ftp.gnu.org/gnu/autoconf/autoconf-$AUTOCONF_VERSION.tar.gz; \
   tar -xvzf autoconf-$AUTOCONF_VERSION.tar.gz; \
    cd /autoconf-$AUTOCONF_VERSION; \
   ./configure; \
   make; \
   make install; \
   rm -rf /autoconf-$AUTOCONF_VERSION.tar.gz; \
   rm -rf /autoconf-$AUTOCONF_VERSION; \
   cd /; \
    \
   git clone --branch=$BISON_VERSION --depth=1 https://github.com/akimd/bison.git /bison; \
   cd /bison; \
   git submodule update --init --recursive; \
   ./bootstrap; \
   ./configure; \
   make; \
   make install; \
   rm -rf /bison; \
   cd /; \
    \
    apt-mark auto '.*' > /dev/null; \
    apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
    rm -rf /var/lib/apt/lists/*
Enter fullscreen mode Exit fullscreen mode

Great! The image has only two layers

docker history bison-test:4.0 --format="table {{.CreatedBy }}\t{{ .Size }}" | grep -v 0B
CREATED BY                                      SIZE
RUN /bin/sh -c set -eux;     apt-get update;…   11.3MB
/bin/sh -c #(nop) ADD file:3ea7c69e4bfac2ebb…   80.5MB
Enter fullscreen mode Exit fullscreen mode

and the total size is 91.8 MB!

docker images --format="table {{.Repository}}\t{{.Tag}}\t{{ .Size }}"  | grep "REPOSITORY\|bison-test"
REPOSITORY    TAG             SIZE
bison-test    4.0             91.8MB
Enter fullscreen mode Exit fullscreen mode

Now you know a few simple steps to make your image smaller:

  • reduce the number of layers
  • remove unnecessary files/dependencies inside the layer where you created it

You can see the original bison Dockerfile here.

Top comments (3)

Collapse
 
abhaysinghr1 profile image
Abhay Singh Rathore

Great tutorial on reducing the size of Docker images by optimizing layers and using scripts to minimize dependencies. Well done!

Collapse
 
iarbatare profile image
DuGut

Hi Anton. Thanks for sharing this with the community.
I am not too experienced into the process of optimizing the size of container image but I am surprised that the size really depends on how many layers you have.

Collapse
 
mizouzie profile image
Sam

This is a great set of instructions, thank you for sharing. I can't wait to try these out on the next image I create.