[docker series] parsing Nginx image Dockerfile line by line (learning classic)


I have always felt that the fastest way to learn programming is to first learn some basic concepts by yourself, and then go to see how Daniel writes code. By imitating Daniel's writing method and then comprehending, it is the fastest way to learn programming . Some friends may say: How can there be so many great codes for you to see, please go to github. There are many official codes of open source organizations. Our study of Dockerfile is no exception. Try to use official resources to learn and see how others write. In this article, we will parse the official nginx image build file Dockerfile line by line with you. The scripts involved in this article can be obtained from the official channel of github:docker-nginx .

1. What is Dockerfile

Dockerfile is a configuration file for automatically building a docker image. The image building process is defined in the Dockerfile by means of instructions. With the docker buildcommand line, you can automate the construction of Docker images.

FROM debian:bullseye-slim

LABEL maintainer="NGINX Docker Maintainers <[email protected]>"

ENV NGINX_VERSION   1.20.2
ENV NJS_VERSION     0.7.0
ENV PKG_RELEASE     1~bullseye

RUN set -x \  #节省篇幅,主要是学习Dcokerfile语法,这里省略了若干行linux的shell脚本

COPY docker-entrypoint.sh /
COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d
COPY 20-envsubst-on-templates.sh /docker-entrypoint.d
COPY 30-tune-worker-processes.sh /docker-entrypoint.d
ENTRYPOINT ["/docker-entrypoint.sh"]

EXPOSE 80

STOPSIGNAL SIGQUIT

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

The picture above is the Dockerfile of the nginx:1.20.2 version of the docker image. Let's parse it line by line.

2. Parse the Dockerfile syntax of nginx

When we learn a language or document grammar, the fastest way to learn is to see how others write it. It is very important who this " other " is here, and the more you play chess with the stinky chess basket, the more stinky you are. So to learn Dockerfile syntax, we need to find a model: you can go to Dockerhub to look at the images officially provided by open source software, you can find the corresponding Dockerfile, and see how others write it.
We use the Dockerfile (officially provided) of the nginx:1.20.2 version of the docker image above, and let's parse its syntax and construction process line by line.

FROM

Generally, we need a basic Linux operating system distribution image to build an image, and on this basis we build our own image.

FROM debian:bullseye-slim

So the role of the FROM instruction is to specify the base image, and the base linux image used by nginx here is debian:bullseye-slim. Among them debian:bullseyeis a version of the debian linux distribution operating system, the version name is bullseye. slimIt usually means that this image is the minimum installation version in the release version, because the image we build is to be propagated in the subsequent continuous integration process and the network between the warehouse and the docker server, so try to make the image build result as much as possible. size is minimized. The selection of the basic image should focus on the size of the size, and the smaller the better if it meets the basic functions of linux and the operation of your program .

LABEL

LABEL is used to add some descriptive and explanatory information to the current image, such as the maintainer and contact information of the current image. It is customized in the form of key-value pairs, and one line can define more than one.

LABEL <key>=<value> <key>=<value> <key>=<value> ...

You can also define multiple lines, such as maintainer maintainer information, description image description information. If the description information cannot be written on one line, you can use "\" to wrap the line. There is an instruction in the Dockerfile syntax called MAINTAINER , which is specially used to describe the maintainer information of the image, but it is now deprecated, and LABEL is used uniformly .

LABEL maintainer="NGINX Docker Maintainers "
LABEL description="This is a Docker image \
for nginx 1.20.2. "

ENV

The role of ENV is to set the environment variable. After the environment variable is set, the variable can be used in the build process and the shell script when the container is running. The usage method is as follows: ${NGINX_VERSION}. Students who have studied JAVA think about how your JAVA_HOME environment variable is set and how to use it? ENV is the same. It's just that the syntax has changed in docker, the syntax format: ENV 环境变量KEY 环境变量Value.

ENV NGINX_VERSION 1.20.2
ENV NJS_VERSION 0.7.0
ENV PKG_RELEASE 1~bullseye

RUN

The function of the RUN instruction is to execute the linux shell script. From the following figure, you can see that the environment variables defined by ENV can be used in the shell script.

For the nginx image, the role of the RUN instruction is to execute a series of shell command lines (scripts) to complete the nginx installation. Therefore, the key to mastering the RUN command is not the RUN command itself, but the key:

  • Will you install nginx manually?
  • Do you know linux's shell script syntax?
  • Can you write the nginx installation process as a shell script?

If the answer to the above three questions is yes, use the RUN command to execute the shell script to complete the software installation. This is also the core of the content of the Dockerfile. The linux shell is not what this article wants to explain.

COPY

The function of the COPY instruction is to copy the local file (the server where the image build is executed) to the image file. The syntax is: COPY <本地文件路径>:<镜像文件路径>, the image file path is also the path to the container runtime file system.

COPY docker-entrypoint.sh /
COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d
COPY 20-envsubst-on-templates.sh /docker-entrypoint.d
COPY 30-tune-worker-processes.sh /docker-entrypoint.d

If the local file path only has the file name, it means that the file and the Dockerfile are in the same directory (relative path syntax). That is: the following files are in the same directory (these files can be seen in the official nginx Dockerfile link I gave above).

Alternatively use the WORKDIR directive to set the local working directory for any RUN, CMD, ENTRYPOINT, COPY, ADD directives that follow it in the Dockerfile. In this way, the relative path mentioned above is the relative path relative to the specified path of WORKDIR. But in general, using WORKDIR is not recommended, because it is difficult to ensure that the working path of the developer's work host executing the build and the working path of the Dockerfile writer are the same.

WORKDIR  /root

ENTRYPOINT

If multiple ENTRYPOINTs are defined in a Dockerfile, only the last ENTRYPOINT takes effect, and every time the docker container is started, the script specified by the ENTRYPOINT will be executed. For nginx:1.20.2, the "/docker-entrypoint.sh" script defines nginx configuration check and nginx service startup instructions. Therefore , the script specified by ENTRYPOINT is usually the startup script of the core service in the image .

ENTRYPOINT ["/docker-entrypoint.sh"]

This script finally executes the nginx service startup, which needs to be completed with the CMD command. Please refer to the CMD command below.

EXPOSE

The Docker container exposes the specified network port at runtime, which can be used for container port mapping. The default protocol is TCP. The format is as follows:

EXPOSE <端口号>
EXPOSE <端口号>/<协议>

After the container port is exposed, a mapping relationship can be established with the port of the host, so that the services inside the container can be accessed by accessing the port of the host. For example, expose the container's port 80 on both TCP and UDP at the same time.

EXPOSE 80/tcp
EXPOSE 80/udp

SUBSTANCE SIGNAL

This instruction is not commonly used by the author. I checked the docker-nginx issue on github and the answer is that the purpose of adding the STOPSIGNAL signal is to prevent the nginx service from being unable to terminate correctly and causing zombie processes after the docker container is stopped. The presence.

STOPSIGNAL SIGQUIT

CMD

The CMD command is also used to execute linux commands or scripts, which is consistent with the RUN command. The difference between the two is

  • The CMD instruction is executed docker runwhen the instruction is executed, that is, when the container is created; and the RUN instruction is executed when the image is built, that is, docker bulidexecuted immediately.
  • It is also because the execution period of the instruction is different that the write operation performed by the RUN name is written to the mirror layer. The execution result of the CMD instruction includes the write operation, which is written to the container layer. (You can refer to my previous article "The Principle of Mirror Layering" to learn and understand).
  • So the CMD and ENTRYPOINT instructions are somewhat similar, both run when the container is created. It should be noted that once the ENTRYPOINT instruction is included in the Dockerfile, the CMD instruction exists as a parameter of the script specified by ENTRYPOINT . See the format syntax below.

CMD contains three formats:

  • The first is the script passing parameters specified by ENTRYPOINT. The last line of the ENTRYPOINT script above exec "$@"is to execute the commands and parameters passed by CMD. to complete the startup of the nginx service. This usage is commonly used in official Dockerfiles (such as: nginx, redis) , which is to do some configuration preparations in the script specified by ENTRYPOINT, and then exec "$@"start the container service by calling the CMD command in the last line of the ENTRYPOINT script.
CMD ["nginx", "-g", "daemon off;"]
  • The second is to execute a command or shell script, you can pass parameters, pay attention to double quotes. The syntax is the same as the first format, except that there is no ENTRYPOINT specified script, so it does not exist as a parameter of the ENTRYPOINT specified script.
CMD ["executable","param1","param2"]
  • The third is the common syntax for executing shell scripts, such as executing echo "This is a test." | wc -cshell command lines. The author said: Do not use this method in Dockerfile, there is no need to know why .
CMD echo "This is a test." | wc -c

Guess you like

Origin blog.csdn.net/hanxiaotongtong/article/details/124441548