How does docker container reduce image size


Write in front

In this short composition, we will learn another key problem of image construction. Why is the image created by others only 10MB and mine a few hundred MB? How to thin the mirror and reduce the mirror volume?

We can cut into thin image from two aspects:

  • Reduce the number of mirror layers
  • Reduced capacity

1, Reduce the number of mirror layers

1. Instruction consolidation

Each instruction in Dockerfile will create a layer, but the best practice in the official document is as follows:

In older versions of Docker, it was important that you minimized the number of layers in your images to ensure they were performant. The following features were added to reduce this limitation:

  • Only the instructions RUN, COPY, ADD create layers. Other instructions create temporary intermediate images, and do not increase the size of the build.


Reference address: Minimize the number of layers

This means that only the RUN, COPY and ADD instructions will create a layer, and other instructions will create an intermediate image without affecting the image size. In this way, the instruction combination we call is mainly based on these three instructions.

Let's take the Dockerfile as an example

FROM debian:stable

WORKDIR /var/www
LABEL version="v1"

RUN apt-get update
RUN apt-get -y --no-install-recommends install curl

RUN apt-get purge -y curl
RUN apt-get autoremove -y
RUN apt-get clean
RUN rm -rf /var/lib/apt/lists/*

Build mirror

docker build -t curl:v1 .

View construction history through history

# docker history curl:v1

IMAGE          CREATED          CREATED BY                                      SIZE      COMMENT
29b721c09b67   18 seconds ago   /bin/sh -c rm -rf /var/lib/apt/lists/*          0B        
aa28ae151e59   20 seconds ago   /bin/sh -c apt-get clean                        0B        
4f733781f557   22 seconds ago   /bin/sh -c apt-get autoremove -y                989kB     
f66887372121   29 seconds ago   /bin/sh -c apt-get purge -y curl                987kB     
d458ee0de463   34 seconds ago   /bin/sh -c apt-get -y --no-install-recommend...   4.46MB    
43fdcf68018c   44 seconds ago   /bin/sh -c apt-get update                       17.6MB    
65631e8bb010   53 seconds ago   /bin/sh -c #(nop)  LABEL version="v1"           0B        
7ef7c53b019c   53 seconds ago   /bin/sh -c #(nop) WORKDIR /var/www              0B        
8bfa93572e55   13 days ago      /bin/sh -c #(nop)  CMD ["bash"]                 0B        
<missing>      13 days ago      /bin/sh -c #(nop) ADD file:d78d93eff67b18592...   124MB 

Mirror size

[root@localhost dockerfiles]# docker images
REPOSITORY            TAG       IMAGE ID       CREATED          SIZE
curl                  v1        29b721c09b67   10 minutes ago   148MB

We combine RUN instructions through shell like operations & & and

RUN apt-get update && \
    apt-get -y --no-install-recommends install curl && \
    apt-get purge -y curl && \
    apt-get autoremove -y && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

View construction history and mirror size

# docker history curl:v2
IMAGE          CREATED              CREATED BY                                      SIZE      COMMENT
928e12c2f57e   About a minute ago   /bin/sh -c apt-get update &&     apt-get -y ...   989kB     
5a32372025fb   About a minute ago   /bin/sh -c #(nop)  LABEL version="v2"           0B        
7ef7c53b019c   30 minutes ago       /bin/sh -c #(nop) WORKDIR /var/www              0B        
8bfa93572e55   13 days ago          /bin/sh -c #(nop)  CMD ["bash"]                 0B        
<missing>      13 days ago          /bin/sh -c #(nop) ADD file:d78d93eff67b18592...   124MB

# docker images
REPOSITORY            TAG       IMAGE ID       CREATED          SIZE
curl                  v2        928e12c2f57e   3 minutes ago    125MB

It can be seen that only a simple curl application has been installed through instruction merging, and the capacity has been released by about 20MB. At the same time, it makes your dockerfile file easier to read and simpler.

2. Multi-stage construction

In docker17 05 introduces multi-stage construction, which can greatly reduce the construction complexity and make it easier to reduce the image size. Let's look at the Dockerfile built in multiple stages

#Phase 1
FROM golang:1.16
WORKDIR /go/src
COPY app.go ./
RUN go build app.go -o myapp
#Phase 2
FROM scratch
WORKDIR /server
COPY --from=0 /go/src/myapp ./
CMD ["./myapp"]

Build mirror

# docker build --no-cache  -t server_app:v2 .

View the built image

# docker images
REPOSITORY            TAG       IMAGE ID       CREATED              SIZE
server_app            v2        20225cb1ea6b   12 seconds ago       1.94MB

The above use cases are from the previous article Dockerfile multi-stage construction practice You can check the specific content of image multi-stage construction, which will not be described here.

3. Enable the square feature

By enabling the square feature (experimental function) docker build -- square - t curl: V3, the built image can be compressed into one layer. However, in order to give full play to the superior design of container image layer sharing, this method is not recommended.

2, Reduced capacity

1. Select a small basic image

The size of each linux distribution image varies a lot, even for the same distribution. Let's take debian as an example:

The difference between the stable version and the slimming version is about 40MB

# docker images 
debian                stable-slim   2aa48a485e3a   13 days ago         80.4MB
debian                stable        8bfa93572e55   13 days ago         124MB

We change the basic image in Dockerfile to Debian: stable slim

FROM debian:stable-slim

The mirror size after construction is smaller

# docker images 
REPOSITORY            TAG           IMAGE ID       CREATED             SIZE
curl                  v4            1aab5c9bf8b3   17 seconds ago      81.4MB

The current image is Debian based and contains many binaries. The Docker container should contain a process and the minimum required to run it. We don't really need the entire operating system.

We can replace the Debian base image with an Alpine based image.

FROM alpine

WORKDIR /var/www
LABEL version="v5"
RUN echo -e '\n' > /etc/apk/repositories && \
    apk update && \
    apk upgrade && \
    apk add --no-cache curl

View mirror size

# docker images
REPOSITORY            TAG           IMAGE ID       CREATED             SIZE
curl                  v5            7f735bb213be   11 seconds ago      10.1MB

At this point, our image comes to 10MB. The alpine image package management tool is apk, and some package names may be different. The biggest difference

2. Context management

We often use the COPY instruction

COPY . /server/dir

COPY copies the entire} build context into the image and produces a new cache layer. In order to load unnecessary files such as logs, cache files and Git history into the construction context, we'd better add them Dockeignore is used to ignore non mandatory files. This is also a key step in streamlining the image, and can better ensure the security of the image we build.

3. Clean up and download in time

We have the following Dockerfile

RUN curl -LO && tar -xf -C /var/www 
RUN rm  -f

Although we used rm to delete download Zip package. Due to the problem of image layering, download Zip is deleted in a new layer, and the previous layer still exists.

We need to clean up and download in time on the first floor

RUN curl -LO && tar -xf -C /var/www &&  rm  -f

In addition, when installing the software, you should use the package management tool to clear the software dependency and cache you downloaded in time, such as using apt package management tool in our dockerfile.

Here are the operations related to thin mirroring.

Keywords: Java Operation & Maintenance Docker RabbitMQ

Added by TheMightySpud on Sat, 18 Dec 2021 07:57:34 +0200