guevara / read-it-later

read it later
232 stars 0 forks source link

Few steps to make your docker image smaller #11897

Open guevara opened 2 weeks ago

guevara commented 2 weeks ago

Few steps to make your docker image smaller

https://ift.tt/S47nIk8

Anton Sukhachev

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

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

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

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 /

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 /
docker build -t bison-test:1.0 .

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 
RUN /bin/sh -c make 
RUN /bin/sh -c ./configure 
RUN /bin/sh -c ./bootstrap 
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 
RUN /bin/sh -c make 
RUN /bin/sh -c ./configure 
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 

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

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

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 

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

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; \ 
    rm -rf /autoconf-$AUTOCONF_VERSION 

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 

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/*
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

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

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/*

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 

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

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.







via mrsuh.com https://mrsuh.com

November 15, 2024 at 06:49PM