[Docker] The road to advancement: (6) Docker image

Understand the composition of mirrors

A mirror is composed of multiple layers. When each layer is superimposed, it looks like an independent object from the outside. Inside the image is a streamlined operating system (OS), which also contains files and dependency packages necessary for application running. Because containers are designed to be fast and small, images are usually smaller. I mentioned many times before that images are like containers (classes) that stop running. In fact, you can stop a container and create a new image from it. Therefore, the image can be understood as a build-time structure, and the container can be understood as a run-time structure.
Insert image description here

Get image

When users create containers, they can create the required images themselves. However, in most cases, users choose to find the required image from the Docker image warehouse. After finding it, download it from the mirror warehouse and use it locally.
First, you need to pull the image from the image warehouse service. A common image repository service is Docker Hub, but other image repository services also exist. The pull operation downloads the image to the local Docker host, which can be used to launch one or more containers.
Docker provides the docker search command to find the image on the remote image warehouse. The use of this command is very simple, its syntax is as follows

docker search keyword

List images

If the user wants to view the image that has been downloaded locally, he can use the dockerimages command. This command can be used directly without any parameters.

[root@docker ~]# docker images
REPOSITORY           TAG                 IMAGE ID       CREATED         SIZE
circle/ubuntu        1.0                 34035f46d2c6   6 seconds ago   72.8MB
circledba/kingbase   v008r006c007b0024   df101ff5974d   41 hours ago    12.4GB
tomcat               latest              fb5657adc892   23 months ago   680MB
ubuntu               latest              ba6acccedd29   2 years ago     72.8MB
centos               7                   eeb6ee3f44bd   2 years ago     204MB

The first column is the image name, the second column is the image label, and the default label is latest: the last label. The third column is the image ID, the fourth column is the image creation time, and the fifth column is the image size.

Delete local image

For images that are no longer needed in the current system, the administrator can delete them to save storage space. To delete an image, use the docker rmi command, where the letter i in rmi represents the image. The basic syntax of this command is as follows:

docker rmi image ...

Where image is the image name. Users can delete multiple images at the same time. Multiple image names are separated by spaces. For example, the following command deletes the local image named tomcat:

[root@docker ~]# docker rmi tomcat
Untagged: tomcat:latest
Untagged: tomcat@sha256:9dee185c3b161cdfede1f5e35e8b56ebc9de88ed3a79526939701f3537a52324
Deleted: sha256:fb5657adc892ed15910445588404c798b57f741e9921ff3c1f1abe01dbb56906
Deleted: sha256:2b4d03a9ce5e200223e5c398d4739d23dd19ad0d6e692cfc65ba3a8fae838444
Deleted: sha256:35c5ea12be1face90896b3a52afc28433885c4448a6c5cfe07561f82365cd18e
Deleted: sha256:6830091c111746b7534960d17f6c156be45d8dcfe0defb06bd427ef38bf49aae
Deleted: sha256:ea82d4efcdfa1c039d722a5a9613c18d3c3a84fbba8efae5e7f13cb3b4ec379f
Deleted: sha256:79a6c362c6b1a580d2d8d33f6d860d45c530f34ff7c0441d36b61aceefdfd656
Deleted: sha256:1788a74c5c86e769f61cd615269eba11c3d7648eac4a85a1ffd2840427820a2f
Deleted: sha256:cbce712ed17923285239f9d9c0528984aef065b7413d68a0290e2c8eecc98f4a
Deleted: sha256:aa56d037ee5925ebf11127c3e1f617874c4ce8bae6b6af7d132b7f7a4a606e6f
Deleted: sha256:97e5f44efb543d466c5847602654a8cb22c9466b61d04988d47ec44b197ea874
Deleted: sha256:11936051f93baf5a4fb090a8fa0999309b8173556f7826598e235e8a82127bce
[root@docker ~]# 

Customized image

Customize the image using Dockerfile

Image customization is actually customizing the configuration and files added at each layer. If we can write the commands for modifying, installing, building, and operating each layer into a script, and use this script to build and customize the image, then the previously mentioned unrepeatable problems, the problem of image construction transparency, and the volume of The problems will all be solved. This script is the Dockerfile.
Dockerfile is a text file whose content contains instructions (Instructions). Each instruction builds a layer, so the content of each instruction describes how the layer should be built.
The following example shows how to use Dockerfile to customize the nginx image.

[root@docker ~]# docker run --name webserver -d -p 80:80 nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
a2abf6c4d29d: Pull complete 
a9edb18cadd1: Pull complete 
589b7251471a: Pull complete 
186b1aaa4aa6: Pull complete 
b4df32aa5a72: Pull complete 
a0bcbecc962e: Pull complete 
Digest: sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
Status: Downloaded newer image for nginx:latest
8dddf86d7a44cb2d19c81fec18c6ea6f4f82626a56133da0723b1a8484f0ec78
[root@docker ~]# 

This command will start a container with the nginx image. The container is named webserver and mapped to port 80, so that you can use the browser to access the nginx server. If Docker is running on the local machine, you can directly access http://localhost; if Docker is installed on a virtual machine or cloud server, localhost needs to be converted to the virtual machine address or the actual cloud server address.
Insert image description hereSuppose you need to modify this page and change it to a text page of "Hello, Docker". You can use the docker exec command to enter the container and modify its content.

[root@docker ~]# docker exec -it webserver bash
root@8dddf86d7a44:/# echo '<h1>Hello,Docker!</h1>' > /usr/share/nginx/html/index.html
root@8dddf86d7a44:/# exit
exit
[root@docker ~]# 

We entered the webserver container through an interactive terminal and executed the bash command, which is to obtain an operable Shell.
Then, use

Hello,Docker!

overwrites the contents of /usr/share/nginx/html/index.html.
If you refresh the browser now, you will find that the page content has been changed. We modified the container's files, which means we changed the container's storage layer. You can view specific changes through the docker diff command.

[root@docker ~]#  docker diff webserver
C /etc
C /etc/nginx
C /etc/nginx/conf.d
C /etc/nginx/conf.d/default.conf
C /root
A /root/.bash_history
C /var
C /var/cache
C /var/cache/nginx
A /var/cache/nginx/client_temp
A /var/cache/nginx/fastcgi_temp
A /var/cache/nginx/proxy_temp
A /var/cache/nginx/scgi_temp
A /var/cache/nginx/uwsgi_temp
C /run
A /run/nginx.pid
C /usr
C /usr/share
C /usr/share/nginx
C /usr/share/nginx/html
C /usr/share/nginx/html/index.html
[root@docker ~]# 

We have customized the changes and hope to save them as a mirror. When we run a container, any file modifications we make will be recorded in the container storage layer. Docker provides a docker commit command, which can save the container's storage layer into an image. In other words, the storage layer of the container is superimposed on the original image to form a new image. When we run this new image in the future, we will have the last file changes of the original container.
The syntax format of docker commit is as follows:

docker commit[选项]<容器ID或容器名>[<仓库名>[:<标签>]]

You can save the container as an image with the following command:

[root@docker ~]# docker commit --author "Circle-DBA <[email protected]>" --message="修改了默认网页" webserver nginx:v2
sha256:fc43cf21d8a7bb25afe7a07f0fa14f106bc3c210346f5e423bb9c71eef8d3a71
[root@docker ~]# 

where –author is the author of the specified modification, and –message records the content of this modification. This is similar to Git version control, but the information here can be left blank and omitted.
You can view this newly customized image in docker image ls:

[root@docker ~]# docker image ls nginx
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
nginx        v2        fc43cf21d8a7   47 seconds ago   141MB
nginx        latest    605c77e624dd   23 months ago    141MB
[root@docker ~]# 

You can also use docker history to specifically view the history in the image. If you compare the history of nginx:latest, you will find that the layer just submitted has been added.

[root@docker ~]# docker history nginx:v2
IMAGE          CREATED              CREATED BY                                       SIZE      COMMENT
fc43cf21d8a7   About a minute ago   nginx -g daemon off;                             1.19kB    修改了默认网页
605c77e624dd   23 months ago        /bin/sh -c #(nop)  CMD ["nginx" "-g" "daemon…   0B        
<missing>      23 months ago        /bin/sh -c #(nop)  STOPSIGNAL SIGQUIT            0B        
<missing>      23 months ago        /bin/sh -c #(nop)  EXPOSE 80                     0B        
<missing>      23 months ago        /bin/sh -c #(nop)  ENTRYPOINT ["/docker-entr…   0B        
<missing>      23 months ago        /bin/sh -c #(nop) COPY file:09a214a3e07c919a…   4.61kB    
<missing>      23 months ago        /bin/sh -c #(nop) COPY file:0fd5fca330dcd6a7…   1.04kB    
<missing>      23 months ago        /bin/sh -c #(nop) COPY file:0b866ff3fc1ef5b0…   1.96kB    
<missing>      23 months ago        /bin/sh -c #(nop) COPY file:65504f71f5855ca0…   1.2kB     
<missing>      23 months ago        /bin/sh -c set -x     && addgroup --system -…   61.1MB    
<missing>      23 months ago        /bin/sh -c #(nop)  ENV PKG_RELEASE=1~bullseye    0B        
<missing>      23 months ago        /bin/sh -c #(nop)  ENV NJS_VERSION=0.7.1         0B        
<missing>      23 months ago        /bin/sh -c #(nop)  ENV NGINX_VERSION=1.21.5      0B        
<missing>      23 months ago        /bin/sh -c #(nop)  LABEL maintainer=NGINX Do…   0B        
<missing>      23 months ago        /bin/sh -c #(nop)  CMD ["bash"]                  0B        
<missing>      23 months ago        /bin/sh -c #(nop) ADD file:09675d11695f65c55…   80.4MB    
[root@docker ~]# 

After the new image is customized, you can run the image.

[root@docker ~]# docker run --name web2 -d -p 81:80 nginx:v2
4ceaadbc86154c3a4a04b87b1c43ab4f6fbdc1fd9b3419f75b689aed37ef66d4

Insert image description here
Here we name the new service web2 and map it to port 81. Visit http://localhost:81 to view the page results. The content should be the same as the previously modified webserver.
So far, we have completed the customized image for the first time. We used the docker commit command to manually add a new layer to the old image to form a new image. Now, we should have a more intuitive feel for mirrored multi-tier storage.
However, docker commit still needs to be used with caution. Although using the docker commit command can help intuitively understand the concept of image tiered storage, it is not used this way in the actual environment.
First of all, if you carefully observe the results of the previous docker diff webserver, you will find that except for the /usr/share/nginx/html/index.html file that you really want to modify, due to the execution of the command, There are also many files that have been changed or added. This is just the simplest operation. If you install software packages, compile and build, a large amount of irrelevant content will be added, which will cause the image to be extremely bloated.
In addition, using docker commit means that all operations on the image are black box operations. The generated image is also called a black box image. In other words, except the person who made the image knows what has been executed. Other than the command and how to generate the image, others have no way of knowing. Moreover, even the person who made the image cannot remember the specific operations after a while. The maintenance of this black box image is very painful.
In addition, recalling the concept of tiered storage used in mirroring mentioned earlier, except for the current layer, each previous layer will not change. In other words, the result of any modification is only to mark, add, and modify the current layer, without changing the previous layer. If you use docker commit to make an image and modify it later, each modification will make the image more bloated. The deleted things on the upper layer will not be lost, and will always follow the image, even if it cannot be accessed at all. The image is more bloated.

Use the docker build command + Dockerfile file to customize the image

Image customization is actually customizing the configuration and files to be added at each layer. If we can write the commands for modifying, installing, building, and operating each layer into a script, and use this script to build and customize the image, then the problems mentioned before that cannot be repeated, the transparency of image construction, and the volume of The problems are all solved. This script is the Dockerfile.
Dockerfile is a text file whose content contains instructions one by one. Each instruction builds a layer, so the content of each instruction describes how the layer should be built.
The following example shows how to use Dockerfile to customize the nginx image. First create a text file in a blank directory and name it Dockerfile:

[root@docker ~]# mkdir mynginx
[root@docker ~]# cd mynginx/
[root@docker mynginx]# touch Dockerfile
[root@docker mynginx]# 

Its content is:

FROM nginx
RUN echo ¹<h1>Hello,Docker!</hl>¹>/usr/share/nginx/html/index.html

This Dockerfile is very simple, with only two lines in total, involving two instructions: FROM and RUN. The FROM instruction is the most important instruction and must be the first non-comment line at the beginning of the Dockerfile file. It is used to specify the base image for the image file building process. Subsequent instructions run in the operating environment provided by this base image. Customized images are all based on FROM images, and nginx here is the basic image required for customization. Subsequent operations are based on nginx. The RUN instruction is used to execute the command line command that follows.
After writing the Dockerfile, start building the image. Use the docker build command to execute the build command in the directory where the Dockerfile file is stored. For example:

[root@docker mynginx]# docker build -t nginx:v3 .
[+] Building 0.6s (6/6) FINISHED                                                             docker:default
 => [internal] load .dockerignore                                                                      0.0s
 => => transferring context: 2B                                                                        0.0s
 => [internal] load build definition from Dockerfile                                                   0.0s
 => => transferring dockerfile: 177B                                                                   0.0s
 => [internal] load metadata for docker.io/library/nginx:latest                                        0.0s
 => [1/2] FROM docker.io/library/nginx                                                                 0.0s
 => [2/2] RUN echo '<h1>Hello,Docker!</hl>' > /usr/share/nginx/html/index.html                         0.4s
 => exporting to image                                                                                 0.0s
 => => exporting layers                                                                                0.0s
 => => writing image sha256:cc54c98400c7db4200160baf22e838488239e8a463b3c925e74f97a4c6f1a88e           0.0s
 => => naming to docker.io/library/nginx:v3                                                            0.0s
[root@docker mynginx]# 

The "." at the end of represents the context path of this execution. The context path means that Docker uses local files (such as copying) when building the image. After the docker build command learns this path, it will package all the content under the path.
In addition to the standard method of using Dockerfile to generate images, due to various special needs and historical reasons, some other methods are also provided to generate images. For example, when importing from a rootfs compressed package, the command format is as follows:

docker import [选项] <文件>|<URL>|-[<仓库名>[:<标签>]]

The compressed package can be a local file, a remote Web file, or even obtained from standard input. The compressed package will be expanded in the image/ directory and submitted directly as the first layer of the image.
Use the docker save command to save the image as an archive file. The command to save the image is:

[root@docker mynginx]# docker save nginx:v3 -o nginxv3
[root@docker mynginx]# file nginxv3
nginxv3: POSIX tar archive
[root@docker mynginx]# 

Note that if the same name exists, it will be overwritten (without warning).
Use gzip compression:

[root@docker mynginx]# docker save nginx:v3 | gzip> nginx-v3.tar.gz
[root@docker mynginx]# ls -l |grep 'nginx'
-rw-------. 1 root root 145911808 129 16:17 nginxv3
-rw-r--r--. 1 root root  54826265 129 16:18 nginx-v3.tar.gz
[root@docker mynginx]# 

Then copy the nginx-v3.tar.gz file to another machine and load the image with the following command:
s docker load -i nginx-v3.tar.gz
Loaded image:nginx:v3
If you combine these two commands with ssh or even pv, using the powerful pipeline of Linux, we can write a command to complete the image Migrate from one machine to another with progress bar function:

docker save <镜像名> | bzip2 | pv |ssh <用户名>@<主机名> 'cat | docker load'

Guess you like

Origin blog.csdn.net/sinat_36528886/article/details/134893820