Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”

What is a Dockerfile?

A Dockerfile is a text file used to build an image. The text content contains the instructions and instructions required to build the image. Using the Docker build command, users can create custom images based on the base image.

Dockerfile format

# Comment INSTRUCTION # Comment INSTRUCTIONCopy the code

Dockerfile instruction in detail

FROM- Specifies the base mirror

Specifies the underlying image, and the first directive in the Dockerfile must be FROM, and multiple FROM directives can be used when creating multiple images in the same Dockerfile.

The syntax is as follows:

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


is optional. If no tag is selected, the default value is latest.

If it is not based on any image, it is written: FROM scratch.

RUN- Runs the specified command

Runs the specified command.

Contains two syntax formats, as follows:

# shell format: Just like a shell script command typed on the command line.
RUN <command> 

Exec format: Just like the format of a function call.
RUN ["executable"."param1"."param2"] 
Copy the code

The first is followed directly by a shell command.

  • On Linux, the default value is/bin/sh -c
  • On Windows, the default value iscmd /S /C

The second is something like a function call. Executable can be understood as an executable, followed by two parameters.

Sample:

RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'

RUN ["/bin/bash"."-c"."echo hello"] 
Copy the code

Note:

Multiline commands do not write multiple runs because each instruction in a Dockerfile creates a layer. The number of runs builds as many layers of images as possible, resulting in bloated, multi-layered images that not only increase the deployment time of components, but also make them prone to errors. The newline character for RUN is \

Cmd-the command to run when the container starts

The command to run when the container starts.

Contains three syntax formats, as follows:

# the first is the shell
CMD command param1 param2

The second option is an executable file with parameters (recommended)
CMD ["executable"."param1"."param2"] 

The ENTRYPOINT directive provides a default parameter for the program specified by the ENTRYPOINT directive
CMD ["<param1>"."<param2>". ]
Copy the code

The second format is recommended because the execution process is relatively clear. The first format is actually automatically converted to the second format as it runs, and the default executable is sh.

Sample:

CMD [ "sh"."-c"."echo $HOME" ]

CMD [ "echo"."$HOME" ] 
Copy the code

Note:

Use double quotation marks (not single quotation marks) for arguments. Never use single quotation marks. The reason is that after the argument is passed, docker parses a JSON array.

ENTRYPOINT- Specifies the default running program for the container

Cmd-like function for specifying the default running program for the container, making it look like a separate executable program.

When writing a Dockerfile, ENTRYPOINT or CMD automatically overwrites the previous ENTRYPOINT or CMD directive. Only one ENTRYPOINT or CMD command can be written. If more than one command is written, only the last entry is valid.

When the Docker image is running, the user can also specify specific commands on the command line, overwriting the commands in the Dockerfile.

Unlike CMD, programs started by ENTRYPOINT are not overwritten by the arguments specified by the Docker Run command line. Moreover, these command-line arguments are passed as arguments to the programs specified by the ENTRYPOINT directive. The –entrypoint option of the Docker run command overrides the program specified by the EntryPoint directive.

The syntax is as follows:

Exec format (recommended)
ENTRYPOINT ["executable"."param1"."param2"] 

# shell format
ENTRYPOINT command param1 param2
Copy the code

The first is an executable file with parameters. Like CMD directives, the exec format is preferred for ENTRYPOINT.

The second is the shell format.

Sample:

FROM ubuntu 
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* 
ENTRYPOINT ["curl"."-s"."http://ip.cn"]
Copy the code
Ubuntu: V1.2, let's create and start the container:Docker run - it ubuntu: v1.2# Will output our corresponding public IP information on the console!
If we need to retrieve HTTP headers, we can do this:Docker run -it Ubuntu :v1.2 -iCopy the code

Similarities and differences between CMD and ENTRYPOINT

These two commands are very desirable and can be used together.

Similarities:

  • You can only write one, and if you write more than one, then only the last one is valid.
  • The container runs only when it is started, at the same time.

Difference:

  • ENTRYPOINT is not overwritten by running commands, whereas CMD is.
  • If we write both ENTRYPOINT and CMD in a Dockerfile, and the CMD directive is not a complete executable command, the contents specified by CMD will be taken as arguments to ENTRYPOINT. As follows:
FROM ubuntu 
ENTRYPOINT ["rm"."docker2"] 
CMD ["-rf"]
Copy the code

The actual command it will execute will be rm docker2-rf.

  • If we write ENTRYPOINT and CMD at the same time in a Dockerfile, and CMD is a complete directive, then the two overwrite each other and whichever takes effect last. As follows:
FROM ubuntu
ENTRYPOINT ["top"."-b"]  
CMD ls -al
Copy the code

Then ls -al will be executed and top -b will not be executed.

The following table shows the commands executed for different ENTRYPOINT/CMD combinations:

  No ENTRYPOINT ENTRYPOINT exec_entry p1_entry ENTRYPOINT [” exec_entry “, “p1_entry”]
No CMD error, not allowed /bin/sh -c exec_entry p1_entry exec_entry p1_entry
CMD [” exec_cmd “, “p1_cmd”] exec_cmd p1_cmd /bin/sh -c exec_entry p1_entry exec_entry p1_entry exec_cmd p1_cmd
CMD [” p1_cmd “, “p2_cmd”] p1_cmd p2_cmd /bin/sh -c exec_entry p1_entry exec_entry p1_entry p1_cmd p2_cmd
CMD exec_cmd p1_cmd /bin/sh -c exec_cmd p1_cmd /bin/sh -c exec_entry p1_entry exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd

Although the two instructions are similar in function, they are not mutually exclusive. In many cases, you can combine ENTRYPOINT and CMD directives to enhance the end user experience. In addition, if the SHELL is used to execute ENTRYPOINT, ENTRYPOINT will ignore any arguments passed from CMD, so it is invalid for CMD to pass only arguments.

Best practices for combining ENTRYPOINT and CMD directives:

Use a combination of ENTRYPOINT and CMD commands to make sure you are using the exec notation. If one of them uses shell notation, or if one is shell notation and the other is exec notation, you will never get what you want. Only if ENTRYPOINT and CMD are both represented in exec notation can the desired effect be achieved.

COPY- Copies files or directories to a specified path in a container

Copies files or directories from the context directory to the specified path in the container.

The syntax is as follows:

COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>"."<dest>"]
Copy the code

Parameter Description:

  • [–chown=:] : Optional. The user changes the owner and owner group of the file copied to the container.
  • < source path >: Source file or source directory. In this case, it can be a wildcard expression. The wildcard rule must meet the Filepath. Such as:COPY hom* /mydir/.COPY hom? .txt /mydir/. The source path must be a path in the build context, not a file in its parent directory. If the source path is a directory, its internal files or subdirectories are copied recursively, butThe source path directory itself will not be copied. If multiple source paths are specified or a wildcard character is used in the source path, the destination path must be a directory and must be set to/At the end.
  • < target path > : specifies the path in the container. It is recommended to use an absolute path for the target path. Otherwise, the COPY command starts with WORKDIR. If the destination path does not already exist, it will be automatically created, including its parent directory path.

Sample:

# copy host file index.html to container /data/ HTML /index.html
COPY index.html /data/html/index.html   

/data/ # copy files (including subdirectories) from host data directory to container /data/
COPYdata /data/
Copy the code

ADD- Copies files or directories to the specified path in the container

The use of the ADD command is similar to that of COPY (COPY is officially recommended for the same requirements) and has similar functions. In addition, ADD supports the use of TAR files and URL paths, and decompresses TAR files (gzip, bzip2, and Xz format). If a URL is specified, the file will be downloaded from the specified URL and placed in the directory (if the URL is a TAR file, it will not be expanded).

The syntax is as follows:

ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>"."<dest>"]
Copy the code

Sample:

ADD. / data/SRC/nginx - 1.14.0 tar. Gz/data/SRC /
Copy the code
# build mirrorDocker build-t nginx:v1.1Create a containerDocker run --rm --name nginx it nginx:v1.1 ls /data/ SRC# nginx-1.14.0.tar.gz file unzipped
Copy the code

LABEL- Specifies the LABEL for the image

Specifies a label for the image in the format:

LABEL <key1>=<value1> <key2>=<value2> ...
Copy the code

LABEL is followed by key-value pairs. Multiple key-value pairs are separated by Spaces. If values contain Spaces, circle values with “”.

If it is too long to wrap a line, use the \ symbol
LABEL name=test \
  description="a container is used to test"
Copy the code

We can use the docker inspect command to view the label of the image:

docker inspect --format '{{json .Config.Labels}}' test | python3 -m json.tool
Copy the code

Where, “test” indicates the container name, and “python3 -m json.tool” indicates that it is formatted as JSON output.

MAINTAINER- Specifies the author name of the image

Specifies the name of the author to generate the image in the following format:

MAINTAINER <name>
Copy the code

The MAINTAINER directive is deprecated and can be used instead with the LABEL directive. For example:

LABEL maintainer='Stephen Chow'
Copy the code

Description:

The LABEL inherits the LABEL in the base image. If the key is the same, the value is overwritten.

EXPOSE- Opens ports specified to listen on for the container to communicate with the outside world

This is used to open a port for the container to listen on in order to communicate with the outside world. This is just a declaration that the “-p” option is used when the container needs to be rebuilt to expose the port. The format is:

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

Example:

EXPOSE 80/tcp
EXPOSE 80/udp
Copy the code

If you want the container to map to the host port, you need to specify -p when starting the container.

The "-p" option is the key. Use the "-p" option in the startup container.
Docker will automatically assign a port and forward the specified port.
Use -p to specify which local port is used to map external ports.Docker run --rm --name nginx-itd -p nginx:v1.4Copy the code

ENV- Sets environment variables

Environment variables defined here can be used either by subsequent directives (such as ENV, ADD, COPY, etc., which call in the format $variable_NAME or ${variable_name}) or by programs running in containers.

It has two syntax formats, as follows:

ENV <key> <value> 

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

The difference between the two is that the first one is set one time, and the second one is set multiple times.

Example:

ENV word hello
RUN echo $word
Copy the code

Note:

If you want to print the environment using the exec format of the CMD or ENTRYPOINT directive, it looks like this:

CMD ["echo", $MODE]

CMD ["echo", "$MODE"]

The value of the environment variable can not be output correctly. You can change the shell format to exec, as shown below:

CMD ["sh", "-c", "echo $MODE"]

In this way, the value of the environment variable can be printed correctly!

ARG- Sets environment variables

The build parameter ARG, like the ENV directive, sets environment variables. But the scope is different. ARG environment variables are only valid in Dockerfile, that is, only in the docker build process, the built image does not exist in this environment variable. These environment variables will not exist in the future when the container runs. But don’t use arGS to store passwords and the like, because docker History is still visible.

ARG build commands can be overridden in docker builds with –build-arg < parameter name >=< value >.

The syntax is as follows:

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

Example:

FROM ubuntu:16.04
ARG app="python-pip"
RUN apt-get update && apt-get install -y $app && rm -rf /var/lib/apt/lists/*

We can define multiple parameters
FROM busybox
ARG user1
ARG buildno

You can also give the parameter a default value
FROM busybox
ARG user1=someuser
ARG buildno=1

# If we specify a default value for ARG, this default value will be used when building the image if no parameter value is specified.
Copy the code

WORKDIR- Specifies the working directory

Set working directories for all RUN, CMD, ENTRYPOINT, COPY, and ADD directives in Dockerfile. The working directory specified with WORKDIR is present at each layer of the build image. WORKDIR Specifies the working directory, which must be created in advance.

Each RUN command in docker build is a new layer. Only directories created by WORKDIR will always exist.

In a Dockerfile file, the WORKDIR directive can appear multiple times, and its path can also be a relative path, but its path is relative to the path specified by the previous WORKDIR directive. In addition, WORKDIR can also call variables defined by ENV.

Format:

WORKDIR< working directory path >
Copy the code

Sample:

WORKDIR /var/log 

Parse environment variables
ENV DIRPATH /path
WORKDIR $DIRPATH

# can also be set multiple times
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
The result of executing PWD is /a/b/c
Copy the code

VOLUME- Defines anonymous data volumes

Define anonymous data volume, can achieve mount function, can be the inland folder or other containers in the folder mounted to this container. If you forget to mount the data volume when starting the container, it will be automatically mounted to the anonymous volume.

Function:

  • Avoid the loss of important data due to container restart, which can be fatal. (The container uses AUFS, a file system that cannot persist data, and all changes are lost when the container is closed.)
  • Avoid growing containers.

The syntax is as follows:

VOLUME ["< 1 > path"."< 2 > path". ]
VOLUMEThe < path >
Copy the code

When starting the container Docker run, we can change the mount point with the -v argument.

Sample:

# define an anonymous volume
FROM ubuntu:16.04
VOLUME /data

# define multiple anonymous volumes
FROM ubuntu:16.04
VOLUME ["/data"."/command"]
Copy the code

The /data and /command directories are automatically mounted as anonymous volumes while the container is running. Any information written to the /data and /command directories is not recorded in the container storage layer, thus ensuring that the container storage layer is stateless! The container anonymous volume directory specifies that overwriting can be done by specifying the -v parameter in the docker run command.

USER- Specifies the USER and USER group to execute the subsequent command

This command is used to specify the user and user group that will execute the subsequent command. Only the user that will execute the subsequent command must already exist. You can RUN the RUN command before the USER command to create the required USER.

By default, the container runs as root.

The syntax is as follows:

You can specify a user name or UID, group name or GID
USER <user>[:<group>]
USER <UID>[:<GID>]
Copy the code

The USER directive can also be overridden with the -u argument in the Docker run command.

Sample:

RUN groupadd -r docker && useradd -r -g docker docker

USER docker
Copy the code

ONBUILD- Used to delay the execution of the build command

Used to delay the execution of build commands. The ONBUILD command in Dockerfile will not be executed during the build process (assuming the image is test-build). When a new Dockerfile is created using a previously built image FROM test-build, the command ONBUILD specified in the Dockerfile of test-build will be executed.

ONBUILD is a special command that is followed by other commands, such as COPY, RUN, etc., that will not be executed when the current image is built. This command is executed only when a next-level image is built based on the current image.

All the other directives in the Dockerfile are for building the current image, only the ONBUILD directive is for helping others customize it.

The syntax is as follows:

ONBUILD< Other instructions >Copy the code

Sample:

from ubuntu:16.04
WORKDIR /data
ONBUILD RUN mkdir test
Copy the code

STOPSIGNAL

Sets the system call signal that will be sent to the container to exit. This signal can be a valid unsigned number that matches a location in the kernel’s Syscall table, such as 9, or a signal name in SIGNAME format, such as SIGKILL.

The syntax is as follows:

STOPSIGNAL signal
Copy the code

The default stop signal is SIGTERM, which will be sent to the docker process whose PID is 1 when the docker stops. The main purpose is to allow applications in the container to do something to smooth out the container after receiving the Signal. If no operation is performed, the container forcibly exits after a period of time, forcing service interruption. The default time is 10 seconds.

HEALTHCHECK- container HEALTHCHECK

Used to specify a program or directive to monitor the running status of docker container services.

The syntax is as follows:

Set the command to check the container health
HEALTHCHECK[OPTIONS] CMD < command >

If the underlying mirror has a health check command, use this line to mask its health check command
HEALTHCHECK NONE

Copy the code

OPTIONS Parameter description:

  • – interval=< interval > : specifies the interval between two checks. The default value is 30s
  • – timeout=< Duration > : specifies the timeout period for running the health check command. If this timeout period is exceeded, the health check fails. The default value is 30 seconds
  • – retries = < number >: Treats the container state as if it has failed a specified number of timesunhealthy, the default value is 3.
  • –start-period=DURATION: Startup time. The default value is 0s. If this parameter is specified, the value must be greater than 0s.--start-periodProvides an initialization period for containers that need to be started, during which the number of failed checks is not recorded. If the health check is successfully performed during startup time, the container is considered to have been started, if during startup timeOnce again,If a check failure occurs, the number of failures is recorded.

Command after the CMD keyword can be a shell command (e.g. HEALTHCHECK CMD /bin/check-running) or an exec array (same as other Dockerfile commands, see [ENTRYPOINT]).

The return value of this command indicates the state of the container, which may be:

  • 0: healthy – container is healthy and can be used;
  • 1: unhealthy – The container does not work properly and needs diagnosis;
  • 2: reserved – Do not use this return value;

When the health state of the container changes, a HEALTH_STATUS event is generated with the new state.

Sample:

HEALTHCHECK --interval=5m --timeout=3s \
  CMD curl -f http://localhost/ || exit 1
Copy the code

Note:

As with CMD and NETRYPOINT, HEALTHCHECK directives can only appear once, and if there are multiple HEALTHCHECK directives, only the last one will take effect!

SHELL- The default SHELL used to override the SHELL format of the XXX directive

The SHELL directive allows you to override the default SHELL used for the SHELL format of the XXX directive. About the default shell, Linux is [“/bin/sh “, “-c”], Windows is [” CMD “, “/ S”, “/ c”].

SHELL instructions must be written in JSON format in a Dockerfile.

SHELL directives are particularly useful on Windows, where there are two commonly used and distinct native shells: CMD and Powershell, and alternate shells available, including sh.

SHELL instructions can appear more than once. Each SHELL instruction overrides all previous SHELL instructions and affects all subsequent ones.

Sample:

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

When using their shell format in dockerfiles, the following directives can be affected by shell directives: RUN, CMD, and ENTRYPOINT.

Refer to the article

  • Official documentation: Dockerfile Reference
  • Docker Dockerfile
  • Dockerfile command description
  • Docker-dockerfile instruction
  • Dockerfile basic instructions and use
  • Dockerfile:ADD VS COPY