Art is long, life is long

First of all, the relationship among Docker image, container and Dockerfile is understood by a picture.

The image is defined using Dockerfile, and the image is run to start the container.

Dockerfile concept

Docker image is a special file system, in addition to providing programs, libraries, resources, configuration files required by the container runtime, but also contains some configuration parameters prepared for the runtime (such as anonymous volumes, environment variables, users, etc.). The image does not contain any dynamic data and its contents are not changed after the build.

The customization of the image is actually customizing the configuration and files that are added to each layer. If we could write each layer of modification, installation, build, and operation commands into a script, and use this script to build and customize the image, the problems of unrepeatability, transparency, and volume mentioned above would all 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. With Dockerfile, when we need to customize our additional requirements, we only need to add or modify instructions on Dockerfile to regenerate the image, saving the trouble of typing commands.

DockerFile instructions

1, FROM specifies the base image

The FROM directive is used to specify the underlying image to be used later to build the new image. The FROM command must be the first command in the Dockerfile file. After the build process starts, Docker will build a new image based on this image, and the commands after the FROM will also be based on this base image.

The syntax format of the FROM is:

FROM <image>
Copy the code
FROM <image>:<tag>
Copy the code
FROM <image>:<digest>
Copy the code

The mirror specified by FROM can be any valid base mirror. FROM has the following restrictions:

  • FROM must be the first non-comment command in Dockerfile
  • When creating multiple images in a Dockerfile file, FROM can appear multiple times. Simply record the last mirror ID committed before each new command FROM.
  • Tag or digest are optional, and if they are not used, the latest version of the base image is used

2. RUN RUN the command

Specific commands are executed during the build of the image and an intermediate image is generated.

#Shell format
RUN <command>
#execformat
RUN ["executable", "param1", "param2"]
Copy the code
  • The RUN command will execute any valid command in the current image and submit the execution result. Once the command execution is committed, the next instruction in the Dockerfile is automatically executed.
  • Hierarchical RUN directives and generate commits are consistent with the core Docker philosophy. It allows custom builds of image images at any point, like version control.
  • The intermediate image created by the RUN directive is cached and used in the next build. If you do not want to use these cache images, you can specify them at build time--no-cacheParameters, such as:docker build --no-cache.

COPY Copies files

COPY < source path >... < target path > COPY ["< source path 1>",... "< target path >"]Copy the code

Like the RUN directive, there are two formats, one similar to the command line and one similar to a function call. The COPY instruction copies files/directories from the < source path > directory in the build context directory to the < destination path > location in the new layer image. Such as:

COPY package.json /usr/src/app/
Copy the code

< source path > can be multiple or even wildcard characters. The wildcard rules must meet the Filepath.Match rule of Go, for example:

COPY hom* /mydir/ COPY hom? .txt /mydir/Copy the code

The < destination path > can be an absolute path within the container or a relative path to the working directory (which can be specified using the WORKDIR directive). The target path does not need to be created in advance. If the directory does not exist, the missing directory is created before the file is copied.

It is also important to note that with the COPY directive, the various metadata of the source file is preserved. Such as read, write, execute permission, file change time and so on. This feature is useful for image customization. This is especially true when the build-related files are managed using Git.

4, ADD more advanced copy files

The format and nature of the ADD instruction and COPY are basically the same.

In the official Docker Dockerfile best practice document, it is required to use COPY as much as possible, because the semantics of COPY are very clear, that is, COPY files, while ADD contains more complex functions, and its behavior may not be very clear. The best places to use ADD are those mentioned where automatic decompression is required.

Also note that the ADD directive invalidates the image build cache, which can make image builds slow.

Therefore, when choosing between COPY and ADD directives, you can follow the principle that COPY is used for all file copies and ADD is used only when automatic decompression is required.

When building an image, copy the files from the context into the image in the following format:

ADD < source path >... < target path > ADD ["< source path >",... "< target path >"]Copy the code

ENV Sets environment variables

There are two formats:

ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
Copy the code

This directive simply sets environment variables, which can be used by any subsequent directive, such as RUN, or by any application at runtime.

ENV VERSION=1.0 DEBUG=on \
    NAME="Happy Feet"
Copy the code

This example shows how to wrap lines and enclose values with Spaces in double quotes, which is consistent with Shell behavior.

6, EXPOSE

Set up listening ports for the built image so that the container listens at run time. Format:

EXPOSE <port> [<port>...]
Copy the code

The EXPOSE directive does not cause the container to listen to the host’s port. If necessary, you need to publish the container port to one of the host’s ports with the -p and -p arguments during docker run.

7. VOLUME Defines an anonymous VOLUME

VOLUME is used to create mount points, that is, to add a VOLUME to a container based on the image being built:

VOLUME ["/data"]
Copy the code

A volume can exist in one or more containers in a specified directory that bypasses the federated file system and has the following capabilities:

  • Volumes can be shared and reused between containers
  • Containers do not have to share volumes with other containers
  • The modification takes effect immediately
  • The volume modification has no impact on the mirror
  • The volume persists until no container is using it

VOLUME lets you add source code, data, or other content to an image without having to hand it in, and it lets you share that content across multiple containers.

CMD container start command

CMD is used to specify the commands to be executed when the container is started. CMD has the following three formats:

CMD ["executable","param1","param2"]
CMD ["param1","param2"]
CMD command param1 param2
Copy the code

Omit the exec format of the executable file. In this way, parameters in CMD are used as default parameters of ENTRYPOINT. In this case, ENTRYPOINT should also be in exec format.

Note the difference with the RUN directive: RUN is executed at build time and generates a new image, CMD is executed while the container is running and does nothing at build time.

9. ENTRYPOINT

ENTRYPOINT specifies the commands to run when the container is started. You can append commands.

ENTRYPOINT is used to configure an executable program for the container. That is, every time a container is created using an image, the program specified through ENTRYPOINT is set as the default program. ENTRYPOINT comes in the following two forms:

ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2
Copy the code

ENTRYPOINT is very similar to CMD, except that commands executed through Docker run do not overwrite ENTRYPOINT, and any parameters specified in the Docker run command are passed to ENTRYPOINT as parameters. Only one ENTRYPOINT command is allowed in a Dockerfile. Multiple ENTRYPOINT commands overwrite previous Settings and only the last ENTRYPOINT command is executed.

Arguments specified by the Docker run container are passed to ENTRYPOINT and overridden by arguments specified by the CMD command. For example, when docker run -d is executed, the -d argument is passed to the entry point.

You can also override entryPoint entry points with Docker Run — EntryPoint. For example, you can specify a container executor as follows:

ENTRYPOINT ["/usr/bin/nginx"]
Copy the code

10. USER Specifies the current USER

USER Specifies the USER for running the image.

USER daemon
Copy the code

When specifying a USER using USER, you can use a USER name, UID, GID, or a combination of the two. The following are all legal designated tests:

USER user
USER user:group
USER uid
USER uid:gid
USER user:gid
USER uid:group
Copy the code

After specifying a USER using USER, the subsequent commands RUN, CMD, and ENTRYPOINT in Dockerfile will use the USER. After the image is built, when the container is run through Docker run, the specified user can be overwritten with the -u parameter.

11. WORKDIR Specifies the working directory

WORKDIR is used to set a working directory within the container:

WORKDIR /path/to/workdir
Copy the code

After setting the working directory through WORKDIR, the subsequent commands RUN, CMD, ENTRYPOINT, ADD, COPY and other commands in Dockerfile will be executed under this directory. For example, use WORKDIR to set the working directory:

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
Copy the code

In the example above, PWD will eventually be executed in the/A /b/c directory. When running the container with Docker Run, you can override the working directory set at build time with the -w argument.

12. LABEL Adds metadata to the image

LABEL is used to add metadata to an image in the form of key/value pairs:

LABEL <key>=<value> <key>=<value> <key>=<value> ...
Copy the code

When LABEL is used to specify metadata, one LABEL can specify one or more metadata. When multiple metadata are specified, the metadata are separated by Spaces. It is recommended to specify all metadata through a LABEL directive to avoid generating too many intermediate images. For example, specify some metadata by LABEL:

LABEL version="1.0" Description =" This is a Web server "by="IT notes"Copy the code

Docker inspect can be used to inspect:

Docker inspect itbilu/test "Labels": {"version": "1.0", "description": "This is a Web server ", "by": "IT notes"},Copy the code

13. ARG construction parameters

ARG is used to specify variables passed to the build runtime:

ARG <name>[=<default value>]
Copy the code

For example, specify two variables via ARG:

ARG site ARG build_user=ITCopy the code

Above we specified the site and build_user variables, where build_user specifies the default value. You can specify or reset the values of these variables with the –build-arg

=

argument when building images with Docker builds.

docker build --build-arg site=itiblu.com -t itbilu/test .
Copy the code

So we build the itbilu/test image, where site will be set to itbilu.com, and since build_user is not specified, the value will be the default IT record.

ONBUILD for others to marry clothes

ONBUILD is used to set the mirror trigger:

ONBUILD [INSTRUCTION]
Copy the code

When the image built is used as a base image for other images, triggers in that image will be fired by the key. For example, when mirroring is used, you may need to do something:

[...].  ONBUILD ADD . /app/src ONBUILD RUN /usr/local/bin/python-build --dir /app/src [...]Copy the code

15, STOPSIGNAL

STOPSIGNAL is used to set the system call signal to be sent by the stop container:

STOPSIGNAL signal
Copy the code

The signal used must be a valid value in the kernel system call table, such as SIGKILL.

16. SHELL instructions

SHELL sets the default SHELL type used to execute commands (shell-style) :

SHELL ["executable", "parameters"]
Copy the code

SHELL is useful in a Windows environment, where there are usually CMD and Powershell shells, and perhaps sh. You can specify the SHELL type to use by SHELL:

FROM microsoft/windowsservercore

# Executed as cmd /S /C echo default
RUN echo default

# Executed as cmd /S /C powershell -command Write-Host default
RUN powershell -command Write-Host default

# Executed as powershell -command Write-Host hello
SHELL ["powershell", "-command"]
RUN Write-Host hello

# Executed as cmd /S /C echo hello
SHELL ["cmd", "/S"", "/C"]
RUN echo hello
Copy the code

DockerFile file format

## Dockerfile file format

# This dockerfile uses the ubuntu image
# VERSION 2 - EDITION 1
# Author: docker_user
# Command format: Instruction [arguments / command]..
 
#1. The first line must specify the underlying mirror information
FROM ubuntu
 
#2. Maintainer information
MAINTAINER docker_user [email protected]
 
#3. Mirror operation instructions
RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list
RUN apt-get update && apt-get install -y nginx
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf
 
#4. The container starts the execution instruction
CMD /usr/sbin/nginx
Copy the code

Dockerfile is divided into four parts: basic image information, maintainer information, image operation instructions, container start execution instructions. You must initially specify the name of the mirror on which you are based, and maintainer information is usually followed; This is followed by mirror operation instructions, such as the RUN directive. Each time the RUN command is executed, a new layer is added to the image and committed; Finally, there is the CMD directive, which specifies the action commands to run the container.

DockerFile instance

Add functionality to the basic centos image

Start a centos image first

[root@jiangwang /]# docker images
REPOSITORY            TAG       IMAGE ID       CREATED        SIZE
tomcat                9.0       040bdb29ab37   8 weeks ago    649MB
tomcat                latest    040bdb29ab37   8 weeks ago    649MB
nginx                 latest    f6d0b4767a6c   8 weeks ago    133MB
centos                latest    300e315adb2f   3 months ago   209MB
portainer/portainer   latest    62771b0b9b09   7 months ago   79.1MB
[root@jiangwang /]# docker run -it centos
[root@124a4f4fda98 /]# pwd
/
[root@124a4f4fda98 /]# vim
bash: vim: command not found
[root@124a4f4fda98 /]# ifconfig
bash: ifconfig: command not found
[root@124a4f4fda98 /]# 
Copy the code

In the container, vim and ipconfig commands are not available. Now we can add some functions to the centos image

#Write a dockerfile file
[root@jiangwang home]# mkdir dockerfile
[root@jiangwang home]# ls
dockerfile  f2  f3  jiangwang  test  test.java  www
[root@jiangwang home]# cd dockerfile/
[root@jiangwang dockerfile]# ls
[root@jiangwang dockerfile]# vim mydocker-centos
[root@jiangwang dockerfile]# cat mydocker-centos 
FROM centos																
MAINTAINER jiangwang<[email protected]>

ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN yum -y install vim
RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD /bin/bash
[root@jiangwang dockerfile]# 

#2. Build the image from this file
#Command docker build -f file path -t Image name :[tag].[root@jiangwang dockerfile]# docker build -f mydocker-centos -t mycentos:0.1..... Successfully built 02b2CC88EF37 Successfully tagged mycentos:0.1 #Copy the code

Start the image and enter the container again to see if the vim and ipconfig commands are available

[root@jiangwang dockerfile]# Docker Images REPOSITORY TAG IMAGE ID CREATED SIZE Mycentos 0.1 02b2CC88EF37 5 minutes ago 291MB Tomcat 9.0 040bdb29AB37 8 weeks ago 649MB tomcat latest 040bdb29AB37 8 weeks ago 649MB nginx latest F6d0b4767a6c 8  weeks ago 133MB centos latest 300e315adb2f 3 months ago 209MB portainer/portainer latest 62771b0b9b09 7 months ago [root@jiangwang dockerfile]# docker run -it mycentos:0.1 [root@4755f8bdac43 local]# PWD /usr/local [root@4755f8bdac43 local]# ifconfig eth0: Flags = 4163 < UP, BROADCAST, RUNNING, MULTICAST > mtu 1500 inet 172.17.0.4 netmask 255.255.0.0 BROADCAST 172.17.255.255 Mr 02:42: AC :11:00:04 TXQueuelen 0 (Ethernet) RX packets 0 bytes 0 (0.0b) RX errors 0 Dropped 0 Overruns 0 frame 0 TX Packets 0 bytes 0 (0.0b) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: Flags =73<UP,LOOPBACK,RUNNING> MTU 65536 inet 127.0.0.1 netmask 255.0.0.0 loop txqueuelen 1000 (Local LOOPBACK) RX Packets 0 bytes 0 (0.0b) RX errors 0 dropped 0 Overruns 0 Frame 0 TX packets 0 bytes 0 (0.0b) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 [root@4755f8bdac43 local]# vim test [root@4755f8bdac43 local]#Copy the code

We found that these commands worked, indicating that the functionality we added was successful.

View historical information about a mirror

[root@jiangwang /]# docker history 02b2cc88ef37 IMAGE CREATED CREATED BY SIZE COMMENT 02b2cc88ef37 11 minutes ago 0B e31AD4Ddeaf0 11 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo...  0B c1b0b4277cf0 11 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B b51a4c01f846 11 minutes ago /bin/sh -c yum -y install Nettools 23.3MB afc7010897bf 11 minutes ago /bin/sh -c yum -y install vim 23.3MB 056EE119a21c 12 minutes ago /bin/sh -c yum -y install vim 23.3MB 056EE119a21c 12 minutes ago /bin/sh -c #(nop) WORKDIR /usr/local 0B 48a552e8da6b 12 minutes ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0B 9621d7bfb61b 12 Minutes ago /bin/sh -c #(nop) MAINTAINER Jiangwang < maintain6...  0B 300e315adb2f 3 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> 3 months ago /bin/sh -c #(nop) LABEL Org.label-schema.sc... 0B <missing> 3 months ago /bin/sh -c #(nop) ADD file:bd7a2aed6ede423b7... 209MB [root@jiangwang /]#Copy the code

Dockerfile Create Tomcat image

1. Prepare the Image file Tomcat package and JDK package

Link: pan.baidu.com/s/1ed1nBYbq… Extraction code: 73S9

-f Dockerfile -f Dockerfile -f Dockerfile -f Dockerfile -f Dockerfile

FROM centos MAINTAINER jiangwang<[email protected]> COPY readme.txt /usr/local/readme.txt ADD jdk-8u161-linux-x64.tar.gz /usr/local/add apache-tomcat-9.0.44.tar.gz /usr/local/run yum -y install vim ENV MYPATH /usr/local/workdir $MYPATH ENV JAVA_HOME /usr/local/jdk1.8.0_161 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.44 ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.44 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin EXPOSE 8080 CMD / usr/local/apache tomcat - 9.0.44 / bin/startup. Sh && tail -f/usr/local/apache tomcat - 9.0.44 / bin/logs/catalina. OutCopy the code

3. Build an image

[root@jiangwang tomcat]# docker build-t mytomcat. Sending build context to docker daemon 201.2MB Step 1/15: FROM centos ---> 300e315adb2f
Step 2/15 : MAINTAINER jiangwang<[email protected]>
 ---> Using cache
 ---> 9621d7bfb61b
Step 3/15 : COPY readme.txt /usr/local/readme.txt
 ---> 5e5723ce3ef3
Step 4/15 : ADD jdk-8u161-linux-x64.tar.gz /usr/local/
 ---> e20cd0601bc1ADD apache-tomcat-9.0.44.tar.gz to /usr/local/ ---> b2f54e1ffad0
Step 6/15 : RUN yum -y install vim
 ---> Running in 0b4b4d2df697

Removing intermediate container 7ede7de98513
 ---> 0c80321324a1Successfully built 0c80321324A1 Successfully tagged Mytomcat :latest # Built SuccessfullyCopy the code

4. Start mirroring (port mapping mounts some directories)

[root@jiangwang tomcat]# docker run -d -p 39001:8080 --name jwtomcat -v / home/jiangwang/tomcat/test: / usr/local/apache tomcat - 9.0.44 / webapps/test - v / home/jiangwang/tomcat/tomcatlogs / : / usr/local/apache tomcat - 9.0.44 / logs mytomcat 9194dbeb2995c314425cf2d9c4776a67122f482d59b068eba4d300ce2661215dCopy the code

5. Intranet test, access successful

[root@jiangwang tomcat]# curl localhost:39001
Copy the code

6, the external network test, also can, (the external network port needs to develop, otherwise can not access) as shown below:

7, Let’s go to the directory where test was mounted and create a simple project to see if it works

Create a new web-INF directory, then create a web. XML file, followed by an index.jsp file

[root@jiangwang tomcat]# ls apache-tomcat-9.0.44.tar.gz Dockerfile JDK-8u161-linux-x64.tar. gz readme. TXT test tomcatlogs  [root@jiangwang tomcat]# cd test [root@jiangwang test]# ls index.jsp WEB-INF [root@jiangwang test]#Copy the code

Enter the following content in the web.xml file:


      
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID"
                    version="2.5">

</web-app>
Copy the code

Enter the contents of the index.jsp file:

<! DOCTYPE html> <html> <head> <meta charset="utf-8">
<title>Tomcat</title>
</head>
<body>
    <h1>
        hello,jiangwang
    </h1>
</body>
</html>
Copy the code

Visit the page and find that the project is running successfully

At this point, a Tomcat image has been successfully created.

Reference documentation

  • Dockerfie official documentation: docs.docker.com/engine/refe…

  • Dockerfile best practice documents: docs.docker.com/develop/dev…

  • Docker Dockerfile: github.com/docker-libr…

  • Docker – From getting started to practice