Docker container (configuration + image creation and Optimization)

Posted by tweet on Mon, 10 Jan 2022 15:21:14 +0100

Docker container (configuration + image creation and Optimization)

I brief introduction

What is Docker

Docker is developed and implemented in Go language introduced by Google. Based on cgroup and namespace of Linux kernel and UnionFS of AUFS class, docker encapsulates and isolates processes, which belongs to virtualization technology at the operating system level. Because the isolated process is independent of the host and other isolated processes, it is also called a container. The initial implementation of Docke was based on LXC
docker is a platform for developers and system administrators to use containers to build, run and share applications. Deploying applications using containers is called containerization

Features of Docker container
Lightweight: faster start-up time
Multiple Docker containers running on a machine can share the operating system kernel of the machine; They can start up quickly and take up very little computing and memory resources.
Standard: consistent operating environment
Docker container is based on open standards and can run on all mainstream Linux versions, Microsoft Windows and any infrastructure including VM, bare metal server and cloud. Docker image provides a complete runtime environment except the kernel to ensure the consistency of application running environment. At the same time, docker ensures the consistency of the execution environment, making it easier to migrate applications; There is no need to worry about the situation that the application cannot run normally due to the change of the operating environment.
Safety: isolation
Docker gives applications isolation not only from each other, but also independent of the underlying infrastructure. Docker provides the strongest isolation by default, so the application problem is only a single container problem, and will not affect the whole machine.
Coherence: continuous delivery and deployment
Docker enables continuous integration, continuous delivery and deployment by customizing application images. Developers can build the image through Dockerfile and conduct integration test in combination with continuous integration system, while operation and maintenance personnel can quickly deploy the image in the production environment directly, or even automatically deploy it in combination with continuous delivery / deployment system.

2, Container configuration

1. Build docker warehouse

Build docker warehouse to facilitate subsequent component installation

[root@server1 ~]# cd /etc/yum.repos.d/
[root@server1 yum.repos.d]# vim westos.repo 
[root@server1 yum.repos.d]# 
[docker]
name=docker-ce
baseurl=http://172.25.6.250/docker-ce
gpgcheck=0
[root@server1 ~]# yum repolist
Loaded plugins: product-id, search-disabled-repos, subscription-manager
This system is not registered with an entitlement server. You can use subscription-manager to register.
docker                                                     | 3.0 kB  00:00:00  dvd                                                        | 4.3 kB  00:00:00  docker/primary_db                                          |  14 kB  00:00:00  repo id              repo name                                         status
docker               docker-ce                                         20
dvd                  rhel7.6                                           5,152
repolist: 5,172

2. Download docker CE, start the service, and start it automatically

[root@server1 ~]# yum install -y docker-ce
[root@server1 ~]# systemctl start docker
[root@server1 ~]# systemctl enable --now  docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.

3. View docker information

[root@server1 ~]# docker info  ##An error is reported

WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled

[root@server1 ~]# cd /etc/sysctl.d
[root@server1 sysctl.d]# ls
99-sysctl.conf
[root@server1 sysctl.d]# vim docker.conf   ##Edit this file to resolve the error

net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1

[root@server1 sysctl.d]# sysctl  --system  ##take effect

After the dcoker CE service is started, docker0, ip address appears

[root@server1 sysctl.d]# ip a  ##docker0, ip appears

Use test of container

[root@server1 ~]# docker load -i mario.tar   ##Load mario application image locally
,This mirror can use: dcoker pull Command direct download
[root@server1 ~]# docker run -d --name demo -p 80:8080 mario  ##Open the demo container and use mario to apply the image
f03d4ece9ed2e8deee25cd434d190b908adb625e90667cb189a6405d6a751905
 notes:Enter: 172 in the web page.25.6.1,Can enter the game mario

[root@server1 ~]# ls
mario.tar
[root@server1 ~]# docker rm -f demo ##Delete container
demo
[root@server1 ~]# docker ps ##Container process view
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@server1 ~]# docker ps -a ##Container all processes view
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

3, docker image

Image -- a special file system
Image is the cornerstone of Docker. Users run their own containers based on images. Mirroring is also a "build" part of the Docker lifecycle. Image is a hierarchical structure based on Federated file system, which is built step by step by a series of instructions

Copy on write can write to the container layer. All mirror layers below the container layer are read-only. docker searches for files from top to bottom. The container layer saves the changed part of the image and does not make any modification to the image itself. A mirror can have up to 127 layers
Image is a read-only container template, which contains the file system structure and content required to start the docker container. Docker encapsulates all components and environments related to the application based on the image and the container built on the image and the unit of container development, testing and publishing, so as to avoid the dependency problems caused by the migration of applications between different platforms, It ensures that the application achieves a highly consistent practical effect in all stages of the production environment
Characteristics of mirror image
Layering mechanism:
Images are built in layers. Each image consists of a series of image layers. When a file in the container needs to be modified, only the top read-write layer is changed, and the contents of the existing file system below are not overwritten. When the modified container file system is submitted as a new image, the saved content is only the updated file in the top-level read-write file system.
Copy on write:

  • Images can be shared among multiple containers, and there is no need to copy a separate image file when each container starts

  • Mount all mirror layers to a mount point in a read-only manner, covering a read-write container layer.

  • Replication on write, combined with the layered mechanism, reduces the disk space occupied by the image and the container startup time

Note: copy on write can write to the container layer. All image layers below the container layer are read-only. docker searches for files from top to bottom. The container layer saves the changed part of the image and does not make any modification to the image itself. There are 127 layers at most for one image

1. Hierarchical structure of image

Load busybox as experimental environment

[root@server1 ~]# docker load -i busybox.tar
[root@server1 ~]# docker history busybox:latest  ## busybox.tar image history view    


Execute the shell, provide an interactive environment, enter the interactive environment, and run the container named demo

[root@server1 ~]# docker run -it  --name demo busybox   
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
/ # touch file1
/ # touch file2     ## CLRT+d launches that interactive environment

[root@server1 ~]# docker ps -a   

Open the demo container and create the material

[root@server1 ~]# docker start 6eced95916b6  ##Open demo container
6eced95916b6
[root@server1 ~]# docker container attach 6eced95916b6  ##Direct access to container
/ # ls
bin    dev    etc    file1  file2  home   proc   root   sys    tmp    usr    var  
/ # touch file3
## CTRL+p+q is to enter the background. You can exit the interactive environment or keep the process
[root@server1 ~]# docker ps -a

[root@server1 ~]# docker rm 6eced95916b6 #
6eced95916b6
[root@server1 ~]# docker run -it --rm busybox

2. Image construction

docker commit creation

  • docker commit build a new image Trilogy
    • Run container
    • Modify container
    • Save the container as a new mirror
  • Disadvantages:
    • Low efficiency, weak repeatability and error prone
    • The user cannot audit the image, which is a potential security hazard
[root@server1 ~]# docker run -it  --name demo busybox  ##Run the container named demo, - i for interactive, - t for open pseudo terminal
/ # touch file1   ##Edit data
/ # touch file2
/ # touch file3
[root@server1 ~]# docker ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
863eb28b2878        busybox             "sh"                52 seconds ago      Up 51 seconds                           demo
[root@server1 ~]# docker commit -m "add files" demo demo:v1  ##Save container as a new image
sha256:4856694c05822d33a952518067b3fcc374442e6882d890763414346625ac2cbe
[root@server1 ~]# docker images  ##View mirror
[root@server1 ~]# docker history demo:v1 ##View v mirror history         
[root@server1 ~]# docker history busybox:latest       ##View busybox: image history,

The above experiments show that v1 image is based on busybox: image

[root@server1 ~]# docker rm demo -f ## -f force deletion of containers
[root@server1 ~]# docker rmi demo:v1 ##Mirror deletion

Through the above experiments and comparing the hierarchical structure, we will find that the manually added container does not explain the role of each layer, so it is built with Dockerfile file

Dockerfile file build

[root@server1 ~]# mkdir docker ##Create dcoker directory
[root@server1 ~]# cd docker
[root@server1 docker]# vim Dockerfile  ##Import, run and modify images by file
```
FROM busybox
RUN touch file1
RUN mkdir westos
```
[root@server1 ~]# docker build -t demo:v1 .

root@server1 ~]# docker history demo:v1

[root@server1 docker]# vim Dockerfile
```bash
FROM demo:v1
RUN touch file2
RUN mkdir redhat
```
[root@server1 ~]# docker build -t demo:v2 .        

[root@server1 ~]#  docker history  demo:v2

4, Detailed explanation of Dockerfile (construction and optimization of nginx image)

4.1 nginx image construction

Here, nginx 'is used as the experimental material to illustrate the situation

[root@server1 docker]# ls   ##First, store the corresponding basic images and files in the docker directory
Dockerfile  nginx-1.20.1.tar.gz  rhel7.tar  westos.repo
[root@server1 docker]# vim Dockerfile
  1 FROM rhel7  ##rhel7 warehouse image
  2 EXPOSE 80  ##Port 80
  3 VOLUME ["/usr/local/nginx/html"]  ##Declare the data volume, specify the application data hanging point,
  4 COPY westos.repo /etc/yum.repos.d/  ##Copy file from build context to image
 Two forms are supported: COPY src dest and COPY ["src", "dest"],src Must specify build context Files or directories in
  5 ADD nginx-1.20.1.tar.gz /mnt  
  6 RUN rpmdb --rebuilddb  
  7 RUN yum install -y gcc pcre-devel zlib-devel make  ##Operation module - software installation
  8 WORKDIR /mnt/nginx-1.20.1   ##Sets the current working directory in the image for the RUN, CMD, ENTRYPOINT, ADD, and COPY directives
  9 RUN ./configure &> /dev/null 
 10 RUN make &>/dev/null
 11 RUN make install &> /dev/null
 12 CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]  ##After nginx is built, close the container
 [root@server1 docker]# docker build -t rhel7:v1 .

 [root@server1 docker]# docker images rhel7   ##View v1 image size
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
rhel7               v1                  400e89940f1a        23 minutes ago      303MB
rhel7               latest              0a3eb3fde7fd        7 years ago         140MB

Run rhel7:v1 image and perform nginx access test

 [root@server1 docker]# docker run -d --name demo3 rhel7:v1
0084a24786e8d05263aec049c1beef00abea42f0bfb44fa28d612a8f94faf0ba

[root@server1 _data]# docker inspect demo3
"Source": "/var/lib/docker/volumes    /ac0e30f4d25df13bcd9e6250160159f6ccfb080754cecdfae1608f77d6ff4686/_data",  ##nginx
 Data volume path
"Gateway": "172.17.0.1",  ##Deploy nginx container gateway
"IPAddress": "172.17.0.3",##ip address for deploying nginx container

In order to make nginx access clearer, add the access page

[root@server1 docker]# cd /var/lib/docker/volumes/ac0e30f4d25df13bcd9e6250160159f6ccfb080754cecdfae1608f77d6ff4686/_data
[root@server1 _data]# ls
[root@server1 _data]# echo nginx-06 > index.html
[root@server1 _data]# curl 172.17.0.3
nginx-06

4.2 nginx image optimization

The v1 image deployed by nginx above reaches 330mb, which is much larger than the 140mb meta image, so the image is optimized
Mirror optimization direction:

Select the most compact basic image, reduce the number of image layers, clean up the intermediate products of image construction, pay attention to optimizing network requests, try to use the construction cache, and use multi-stage image construction

4.2.1 optimized basic version of nginx image

Reduce the number of image layers, merge all RUN instructions, and clean up the intermediate products of image construction, including the compiled installation package and cache / mnt/nginx-1.20.1 /var/cache/*

[root@server1 docker]# vim Dockerfile 
FROM rhel7 
EXPOSE 80
COPY dvd.repo /etc/yum.repos.d/
ADD nginx-1.20.1.tar.gz /mnt
WORKDIR /mnt/nginx-1.20.1
RUN rpmdb --rebuilddb &&  yum install -y gcc pcre-devel zlib-devel make && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc  && ./configure &> /dev/null && make &> /dev/null &&  make install &> /dev/null && rm -fr /mnt/nginx-1.20.1 /var/cache/* 
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
[root@server1 docker]# docker build -t rhel7:v2 . ##Create v2 image

[root@server1 docker]# docker images  

4.2.2 optimized advanced version of nginx image

The v2 image deployed by nginx above is 255mb, which is still much larger than the 140mb meta image, so continue to optimize the image
The best optimization of single-phase image has reached its limit, so try to use build cache and use multi-phase build image

[root@server1 docker]# vim Dockerfile 
FROM rhel7 
EXPOSE 80
COPY dvd.repo /etc/yum.repos.d/
ADD nginx-1.20.1.tar.gz /mnt
WORKDIR /mnt/nginx-1.20.1
RUN rpmdb --rebuilddb &&  yum install -y gcc pcre-devel zlib-devel make && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc  && ./configure &> /dev/null && make &> /dev/null &&  make install &> /dev/null && rm -fr /mnt/nginx-1.20.1 /var/cache/* 
FROM rhel7
COPY --from=build /usr/local/nginx /usr/local/nginx
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
[root@server1 docker]# docker build -t rhel7:v3 . ##Create v3 image

[root@server1 docker]# docker images 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

<none>              <none>              66a3cc6f8627        26 seconds ago      255MB
rhel7               v3                  a7c6b4e995d5        26 seconds ago      141MB
rhel7               v1                  400e89940f1a        About an hour ago   303MB
rhel7               latest              0a3eb3fde7fd        7 years ago         140MB

4.2.3 optimized sublimation version of nginx image

The v3 image deployed by nginx above is 141mb, but the image optimization can still be continued
Starting from the source, select a simplified basic image to replace the original rhel7
Load base image locally

[root@server1 docker]# docker load -i base-debian10.tar  ##Thin base image -- base debian10
de1602ca36c9: Loading layer  3.041MB/3.041MB
1d3b68b6972f: Loading layer  17.77MB/17.77MB
Loaded image: gcr.io/distroless/base-debian10:latest

[root@server1 docker]# vim Dockerfile 
vim /Dockerfile

FROM nginx:latest 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;"]
[root@server1 docker]# docker build -t rhel7:v4 .

[root@server1 docker]# docker images rhel7 ##View rhel7 mirror

[root@server1 docker]#  docker run -d --name demo4 rhel7:v4  ##Run the v4 image to deploy and open nginx inside the container
1f881774fce4890c42472aec424dad4f425eefb277691fe2fb9e369e7b898408
[root@server1 docker]# docker inspect demo4  ##View container information

"IPAddress": "172.17.0.4",
[root@server1 docker]# curl 172.17.0.4  ##Access nginx

[root@server1 ~]# docker exec -it demo4 bash  ##Enter the demo4 container and write the access page of nginx
bash-4.2# cd /usr/local/nginx/html/  ##Access directory of nginx
bash-4.2# echo westos > index.html  ##index.html: default access file
bash-4.2# curl  localhost
westos
bash-4.2# exit
[root@server1 ~]# curl 172.17.0.4
westos

Topics: Operation & Maintenance