docker's nginx image optimization 4

Posted by pradeepknv on Fri, 04 Feb 2022 06:17:55 +0100

Thin images have been selected, so reduce the number of layers of images and merge the previous runs together. Switch WORKDIR to cd under RUN
Previous Dockerfile:

FROM rhel7
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
COPY dvd.repo /etc/yum.repos.d/dvd.repo
RUN rpmdb --rebuilddb
RUN yum install -y gcc pcre-devel zlib-devel 
ADD nginx-1.18.0.tar.gz /mnt
WORKDIR /mnt/nginx-1.18.0
RUN ./configure --prefix=/usr/local/nginx
RUN yum install make -y
RUN make
RUN make install
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]

After reducing the number of mirror layers:

[root@docker1 docker]# cat Dockerfile 
FROM rhel7
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
COPY dvd.repo /etc/yum.repos.d/dvd.repo
ADD nginx-1.18.0.tar.gz /mnt
RUN rpmdb --rebuilddb && yum install -y gcc pcre-devel zlib-devel && cd /mnt/nginx-1.18.0 && ./configure --prefix=/usr/local/nginx && yum install make -y && make && make install
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]

Clean up the cache path of the intermediate product: / var / cache / yum, delete the nginx installation package, and delete the make gcc after compiling (dependencies will be installed when installing make packages, but they will not be deleted when deleting them)

[root@docker1 docker]# cat Dockerfile 
FROM rhel7
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
COPY dvd.repo /etc/yum.repos.d/dvd.repo
ADD nginx-1.18.0.tar.gz /mnt
RUN rpmdb --rebuilddb && yum install -y gcc pcre-devel zlib-devel make && cd /mnt/nginx-1.18.0 && ./configure --prefix=/usr/local/nginx && make && make install  && rm -fr /mnt/nginx-1.18.0 /var/cache/yum 
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]
[root@docker1 docker]# docker build -t webserver:v2 .

Mirror size gap after optimization:

[root@docker1 docker]# docker images webserver
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
webserver           v2                  503439033877        24 seconds ago      258MB
webserver           v1                  bdd2829a42e3        36 minutes ago      346MB
[root@docker1 docker]# docker images rhel7
rhel7               latest              0a3eb3fde7fd        7 years ago         140MB

Optimized: 346-258. It's more than 140 base images

It can be seen that most of them are 111MB in Yum, and this layer is mainly used for installation package compilation, etc

[root@docker1 docker]# docker history webserver:v2
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
503439033877        6 minutes ago       /bin/sh -c #(nop)  CMD ["/usr/local/nginx/sb...   0B                  
c140026256fd        6 minutes ago       /bin/sh -c rpmdb --rebuilddb && yum install ...   111MB               
8b163bc5912e        7 minutes ago       /bin/sh -c #(nop) ADD file:a90dc1ecadbd423a5...   6.25MB              
b17ef4913f9c        48 minutes ago      /bin/sh -c #(nop) COPY file:fe5cdcb63a06bd4c...   67B                 
82ca7e5c38e6        49 minutes ago      /bin/sh -c #(nop)  VOLUME [/usr/local/nginx/...   0B                  
8aa3b0c110c7        49 minutes ago      /bin/sh -c #(nop)  EXPOSE 80                    0B                  
0a3eb3fde7fd        7 years ago                                                         140MB               Imported from -

It can be seen that when v1 is not optimized, you can only use yum code.

[root@docker1 docker]# docker history webserver:v1
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
bdd2829a42e3        44 minutes ago      /bin/sh -c #(nop)  CMD ["/usr/local/nginx/sb...   0B                           
9e03306cbffd        44 minutes ago      /bin/sh -c yum install make -y                  43.6MB                         
bf1e3007a03b        49 minutes ago      /bin/sh -c yum install -y gcc pcre-devel zli...   133MB               

After compiling the source code, you really only need the compiled binary code
Therefore, I really only need the binary code of / usr/local/nginx, which is only 5M, and the rest (intermediate products) do not need it. If I turn off debug, it will be less than 1M
You can only compile the source code (binary code) of the operating system for direct use by other operating systems

Use multistage build

It is divided into two parts. First compile the binary code in one container, and then copy it to the second container for use
Comment out debug

[root@docker1 nginx-1.18.0]# vim auto/cc/gcc 

[root@docker1 nginx-1.18.0]# sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc 


Replace all completed
Add the instruction to the Dockerfile and build it in multiple stages (use the binary code of nginx compiled by the previous container)
as build is named build
COPY --from=build /usr/local/nginx /usr/local/nginx put the binary encoding directory of the previous container (/ usr/local/nginx) in / usr/local/nginx of the next container
It is not necessary to expose ports and volumes, so it is deleted and a streamlined Dockerfile is compiled

[root@docker1 docker]# cat Dockerfile 
FROM rhel7 as build
COPY dvd.repo /etc/yum.repos.d/dvd.repo
ADD nginx-1.18.0.tar.gz /mnt
RUN rpmdb --rebuilddb && yum install -y gcc pcre-devel zlib-devel make && cd /mnt/nginx-1.18.0 && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc  && ./configure --prefix=/usr/local/nginx && make && make install  && rm -fr /mnt/nginx-1.18.0 /var/cache/yum 

FROM rhel7
COPY --from=build /usr/local/nginx /usr/local/nginx
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]

[root@docker1 docker]# docker build -t webserver:v3 .

Remove the 140MB basic image base and an nginx 1MB

[root@docker1 docker]# docker images webserver
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
webserver           v3                  5cd6dd1fdc7f        31 seconds ago      141MB
webserver           v2                  503439033877        35 minutes ago      258MB
webserver           v1                  bdd2829a42e3        About an hour ago   346MB

It must be nginx OK for docker to run. CMD reports errors when there are problems

[root@docker1 docker]# docker run -d --name nginx webserver:v3
[root@docker1 docker]# docker container inspect nginx | grep "IPAddress"
            "IPAddress": "172.17.0.2",
[root@docker1 docker]# curl 172.17.0.2
<h1>Welcome to nginx!</h1>

No optimization can be smaller than the base image
Therefore, we need to find a more streamlined base in optimization https://hub.docker.com/ Find or www.github.com Com or www.gitee.com Com

When nginx is running, it will call the dynamic library file of the system
Library files are indispensable. Without binary files, you can't get up.
Therefore, when copying the binary file directory, the library files should also be included. At the same time, the library files called by different compiled nginx are also different. Opensll and Lib opensll libraries are added. Therefore, if you exchange smaller images, you need to migrate the library files and binary files at the same time. At the same time, we should also consider whether these library files are dependent or not, and call other library files.

[root@docker1 docker]# docker run -it --rm webserver:v3 bash
bash-4.2# ldd /usr/local/nginx/sbin/nginx 
	linux-vdso.so.1 =>  (0x00007ffc06f6d000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007f3560c8a000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f3560a6e000)
	libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f3560837000)
	libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f35605d6000)
	libz.so.1 => /lib64/libz.so.1 (0x00007f35603c0000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f355ffff000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f3560e8e000)
	libfreebl3.so => /lib64/libfreebl3.so (0x00007f355fd80000)

Search github for destroy, Google's container tool.

download
I use debian10 to import images.

[root@docker1 docker]# docker load -i base-debian10.tar 

The base image is small

[root@docker1 docker]# docker images 
gcr.io/distroless/base-debian10   latest              d48fcdd54946        52 years ago        19.2MB

First, search github for troubleshooting nginx and go in

Then check the Dockerfile written by others. It can be seen that it uses the smallest image provided by the official, and it is a multi-stage construction, and the library file of the system is included.
Write Dockerfile2

[root@docker1 docker]# cat Dockerfile2
FROM nginx:1.18.0 as base

# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
ARG TIME_ZONE

RUN mkdir -p /opt/var/cache/nginx && \
    cp -a --parents /usr/lib/nginx /opt && \
    cp -a --parents /usr/share/nginx /opt && \
    cp -a --parents /var/log/nginx /opt && \
    cp -aL --parents /var/run /opt && \
    cp -a --parents /etc/nginx /opt && \
    cp -a --parents /etc/passwd /opt && \
    cp -a --parents /etc/group /opt && \
    cp -a --parents /usr/sbin/nginx /opt && \
    cp -a --parents /usr/sbin/nginx-debug /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/ld-* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libpcre.so.* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libz.so.* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libc* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libdl* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libpthread* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libcrypt* /opt && \
    cp -a --parents /usr/lib/x86_64-linux-gnu/libssl.so.* /opt && \
    cp -a --parents /usr/lib/x86_64-linux-gnu/libcrypto.so.* /opt && \
    cp /usr/share/zoneinfo/${TIME_ZONE:-ROC} /opt/etc/localtime

FROM gcr.io/distroless/base-debian10

COPY --from=base /opt /

EXPOSE 80 443

ENTRYPOINT ["nginx", "-g", "daemon off;"]

To build an image, - f specify dockerfile2, otherwise the default Dockerfile will be read

[root@docker1 docker]# docker build -t webserver:v4 -f Dockerfile2 .

effect

[root@docker1 docker]# docker images webserver
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
webserver           v4                  0fce27d5ac56        15 seconds ago      31.7MB

Run the container successfully.

[root@docker1 docker]# docker run -d --name nginx webserver:v4
[root@docker1 docker]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
79bc3e329d8f        webserver:v4        "nginx -g 'daemon of..."   23 seconds ago      Up 22 seconds       80/tcp, 443/tcp     nginx
[root@docker1 docker]# docker inspect nginx | grep IP
                    "IPAddress": "172.17.0.2",

Visit successful

[root@docker1 docker]# curl 172.17.0.2
<h1>Welcome to nginx!</h1>

Topics: Operation & Maintenance Docker Nginx