This article has participated in the Denver Nuggets Creators Camp 3 “More Productive writing” track, see details: Digg project | creators Camp 3 ongoing, “write” personal impact.

1 FROM

1.1 FROM Specifies a base mirror

The customization of the image is actually customizing the configuration and files that are added to each layer. If you can write each layer of modify, install, build, and manipulate commands into a script, and use this script to build and customize the image, then the aforementioned problems of unrepeatability, transparency, and volume will be solved. This script is called Dockerfile.

Dockerfile is a text file containing instructions, each Instruction builds a layer, so the content of each Instruction describes how the layer should be built.

Using the nginx image as an example, this time we will use Dockerfile to customize it.

Create a text file in a blank directory and name it Dockerfile:

$ mkdir mynginx
$ cd mynginx
$ touch Dockerfile
Copy the code

Its contents are as follows:

FROM nginx RUN echo '<h1>Hello, Docker! </h1>' > /usr/share/nginx/html/index.htmlCopy the code

This Dockerfile is very simple, just two lines in total. There are two instructions involved, FROM and RUN.

1.2 FROM Specifies the base image

The so-called custom mirror, that must be based on a mirror, on its customization. Just as we ran an Nginx image container and then modified it, the base image must be specified. FROM specifies the base image, so in a Dockerfile, FROM is the required instruction and must be the first instruction.

Docker Hub has a lot of high quality official images, there are directly used service class images, such as Nginx, Redis, Mongo, mysql, HTTPD, PHP, tomcat, etc. There are also images for developing, building, and running applications in various languages, such as Node, OpenJDK, Python, Ruby, Golang, etc. We can customize the base image by looking for the one that best fits our final goal.

If you cannot find the corresponding service image, the official image also provides some more basic OPERATING system images, such as Ubuntu, Debian, centos, Fedora, alpine, and so on. These operating system software libraries provide a broader space for expansion.

2 RUN

2.1 RUN RUN the command

The RUN command is used to execute command line commands. Because of the power of the command line, the RUN directive is one of the most commonly used directives when customizing images. There are two formats:

  • shellFormat:RUN < command >, just like a command typed directly from the command line. In the Dockerfile I just wroteRUNInstructions are in this format.
RUN echo '<h1>Hello, Docker! </h1>' > /usr/share/nginx/html/index.htmlCopy the code
  • execFormat:RUN [" executable ", "parameter 1"," parameter 2"]This is more like the format in a function call.

Since RUN can execute commands just like Shell scripts, can we have a RUN for each command just like Shell scripts? Like this:

FROM debian:stretch RUN apt-get update RUN apt-get install -y gcc libc6-dev make wget RUN wget -O redis.tar.gz "Http://download.redis.io/releases/redis-5.0.3.tar.gz" RUN the mkdir -p/usr/SRC/redis RUN tar - XZF redis. Tar. Gz - C /usr/src/redis --strip-components=1 RUN make -C /usr/src/redis RUN make -C /usr/src/redis installCopy the code

As mentioned earlier, every instruction in a Dockerfile creates a layer, and RUN is no exception. The behavior of each RUN is the same as that of the manual mirroring process: create a new layer, execute these commands on it, and commit the layer changes to form a new image.

This way, it creates seven mirrors. This makes no sense at all, and many things that are not needed at runtime are loaded into the image, such as compilation environments, updated packages, and so on. The result is a very bloated, multi-tiered image that not only increases build and deployment time, but is also prone to error. This is a common mistake many Docker beginners make.


U n i o n F S There is a maximum number of layers, for example A U F S , used to be the maximum 42 Layers are now not to be exceeded 127 Layer. \color{red}{Union FS has a maximum number of layers, such as AUFS, which used to have a maximum of 42 layers, now has a maximum of 127 layers. }

The correct way to write the Dockerfile above should look like this:

FROM debian:stretch RUN buildDeps='gcc libc6-dev make wget' \ && apt-get update \ && apt-get install -y $buildDeps \ && Wget -o redis. Tar. Gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \ && mkdir -p/usr/SRC/redis \ && tar - XZF redis.tar.gz -C /usr/src/redis --strip-components=1 \ && make -C /usr/src/redis \ && make -C /usr/src/redis install \ &&  rm -rf /var/lib/apt/lists/* \ && rm redis.tar.gz \ && rm -r /usr/src/redis \ && apt-get purge -y --auto-remove $buildDepsCopy the code

First of all, all the previous commands had only one purpose, which was to compile and install the Redis executable. So there’s no need to build many layers, it’s just a one layer thing. Therefore, instead of using multiple RUN pairs to correspond to different commands, you use just one RUN directive and chain the required commands together using &&. I’m going to simplify the previous 7 layers to 1 layer. When writing a Dockerfile, always remind yourself that you are not writing a Shell script, but defining how each layer should be built.

Also, there are line breaks for formatting purposes. Dockerfile supports Shell classes to add ‘ ‘to the end of the line, as well as the first line of the comment format. Good formatting, such as line breaks, indentation, comments, etc., makes maintenance and elimination easier, which is a good habit.

In addition, you can also see that a cleanup command was added at the end of this set of commands, deleting the software needed for the build, cleaning up all downloaded and expanded files, and cleaning up the APT cache files. This is an important step, as we said before, mirrors are layers of storage, and things on each layer don’t get deleted from the next layer, they follow the image. So when building a mirror, make sure that each layer only adds what really needs to be added. Anything that doesn’t need to be added should be removed.

3 BUILD

3.1 Building an Image

Run the following command in the Dockerfile directory:

$docker build -t nginx:v3. Sending build context to docker daemon 2.048 kB Step 1: FROM nginx ---> e43d811ce2f4 Step 2 : RUN echo '<h1>Hello, Docker! </h1>' > /usr/share/nginx/html/index.html ---> Running in 9cdc27646c7b ---> 44aa4490ce2c Removing intermediate container  9cdc27646c7b Successfully built 44aa4490ce2cCopy the code

In the command output, you can clearly see the image construction process. In Step 2, as mentioned earlier, the RUN directive starts a container, 9CDc27646C7b, executes the required commands, and finally commits the layer 44AA4490CE2C, then deletes the container used.

Here we use the Docker build command to build the image. The format is:

Docker build [options] < context path /URL/->Copy the code

Here we specify the name of the final image: -t nginx:v3. Once the build is successful, we can run the image just as we ran nginx:v2, and the result will be the same as nginx:v2.