Detailed explanation of Dockerfile instruction & an example of image construction

Dockerfile Usage Summary

  • Dockerfile is a text file used to build an image, which contains instructions and instructions for building an image.
  • Each layer instruction in the dockerfield file describes how to build this layer on the basis of the previous layer.

Operating environment

  • Alibaba cloud ubuntu 20.04

Building a simple instance of a mirror

  • Take ubuntu as an example to build a simple image:

    # Create a new Dockerfile folder and create a Dockerfile
    $ mkdir Dockerfile
    $ cd Dockerfile
    $ vi Dockerfile

    Write in Dockerfile:

    FROM ubuntu
    MAINTAINER test-user
    RUN echo "Test build image" > /test.txt

    The first line of instruction: this image is built based on ubuntu;

    The second line of instruction: the image maintenance personnel information;

    The third line of instruction: in the process of docker build, write "test build image" to test TXT text file.

    To build a mirror:

    $ docker build -t ubuntu:test .
    Sending build context to Docker daemon  2.048kB
    Step 1/2 : FROM ubuntu
     ---> ba6acccedd29
    Step 2/2 : RUN echo "Test build image" > /test.txt
     ---> Running in 3eea459154d9
    Removing intermediate container 3eea459154d9
     ---> 5279a6de02d5
    Successfully built 5279a6de02d5
    Successfully tagged ubuntu:test

    As you can see, it's in step 2. The RUN instruction starts the container ba6acccedd29, runs the command of the RUN instruction, and then deletes the image.

    Check whether the image is successfully built:

    $ docker run -it ubuntu:test /bin/bash
    root@fa8a1142b131:/ cat test.txt 
    Test build image

    The image was built successfully.

Context path

  • In the above example, the command to build an image is: docker build -t ubuntu:test- The T attribute indicates the warehouse and label of the built image It means that the Dockerfile file is in the current folder. If the build command is executed in the root directory, the path is / Dockerfile. This path is the context path, which indicates the path where the file required to build the image is located. The path where the Dockerfile is located is used by default.
  • In the process of building an image, if there is a COPY instruction, the file to be copied is also placed in the context path.
  • It is better not to put files irrelevant to the image construction in the context path, because the image construction process of Docker actually takes place in the Docker engine. During the construction process, the files under this path will be packaged to the engine, and too many files will slow the construction process.

Detailed explanation of instruction meaning


  • Customized images are all FROM based images
  • DOcker has a special image scratch, that is, a blank image. If FROM scratch, it means that the next instruction is the first layer of the image.


  • Each RUN instruction creates a new layer, then executes the command, and submits the modifications of this layer to form a new image.

  • Dockerfile is different from shell script. Each RUN instruction will build a layer. Therefore, try to write the commands of multiple RUN instructions in the same RUN instruction. Different commands can be wrapped and connected with &. In order to reduce the size of the image, additional unnecessary contents need to be deleted in the instruction, such as:

    FROM debian:stretch
    RUN set -x; buildDeps='gcc libc6-dev make wget' \
        && apt-get update \
        && apt-get install -y $buildDeps \
        && wget -O redis.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 $buildDeps

    Firstly, the instructions are to compile and install redis executable files. Secondly, you can see that the cleaning command is added at the end of this group of commands, the software required for compilation and construction is deleted, all downloaded and expanded files are cleaned, and apt cache files are also cleaned.

  • Used to execute subsequent commands during construction. There are two formats:

#shell format
RUN echo "test" > ./test.txt
#exec format
RUN ["echo", "test", "./test.txt"]


  • Copy the file or directory from the context path to the specified directory in the container.
COPY <from path> <Target path>
  • The target path does not need to be built in advance. If it does not exist, it will be created automatically


  • The function and usage are similar to that of COPY, which is officially recommended.

  • Advantages: when the < source file > is a tar compressed file and the file format is bzip\gzip2\xz, the source file will be copied and decompressed to the target path;

  • Disadvantages: the tar compressed file cannot be copied without decompression, which will invalidate the image build cache and make the image build very slow.


  • Similar to the RUN instruction, it is used to RUN programs, but the running time of the two is different:

  • The RUN instruction runs when building an image, that is, when docker build s;

  • The CMD instruction runs when the container is started with the built image, that is, when docker run s.

  • CMD can be written in three ways:

# exec mode
CMD ["top"]
# shell mode
CMD top
# The third way is to provide parameters for the default program specified by the ENTRYPOINT instruction
CMD ["param1", "param2"]
  • The difference between CMD's exec mode and shell mode is that process 1 is different when the container is started. For details, see "differences between Dockerfile#CMD's exec mode and shell mode. md".

  • CMD instruction is used to specify the program to be run by default when the container starts, and the container ends when the program runs. However, the running program specified in the docker run command can override the default running program specified by CMD.

  • The disadvantage of CMD is that if you want to specify the running program for CMD during docker run and pass in other parameters, you need to input the CMD instruction again, that is, the parameters cannot be passed into the CMD instruction written during construction.

#Suppose that the Dockerfile of the image ubuntu:test specifies that the default program is to run top
CMD ["top"]
#Build image ubuntu:test
#Start the container with ubuntu:test
docker run -it ubuntu:test /bin/bash

#After the container runs, the / bin/bash command actually runs instead of the default top command
  • If there are multiple CMD instructions in Dockerfile, only the last instruction takes effect.


  • The function is similar to CMD, but when the – entrypoint parameter is not used, the instruction of the docker run command line instruction will not overwrite the entrypoint instruction like the CMD instruction, but pass the parameters and commands specified by docker run to the entrypoint instruction as parameters.

  • If there is an ENTRYPOINT in Dockerfile, the CMD instruction content will be used as the parameter of the ENTRYPOINT instruction.

  • docker run --entrypoint <command> inamge_ The command after name, - entrypoint will override the entrypoint command.

  • Advantages: unlike when you want to modify the CMD instruction when docker run, you can only re formulate the command specified by the CMD instruction after docker run. The ENTRYPOINT instruction supports passing parameters to the ENTRYPOINT instruction when docker run.

  • If there are multiple entrypoints in Dockerfile, only the last one will take effect.

  • Write Dockerfile file:

    FROM ubuntu
    RUN ["echo", "Test image",">","./test.txt"]
    ENTRYPOINT ["echo", "Hello"]
    CMD ["World"]

    Build test image test/ubuntu:v1

    $ docker build -t test/ubuntu:v1 .
    Sending build context to Docker daemon  2.048kB
    Step 1/5 : FROM ubuntu
     ---> ba6acccedd29
    Step 2/5 : MAINTAINER klw
     ---> Running in df34ca2e01c0
    Removing intermediate container df34ca2e01c0
     ---> 9c154c5d6c72
    Step 3/5 : RUN ["echo", "Test image",">","./test.txt"]
     ---> Running in 66a7bb885da8
     Test image > ./test.txt
    Removing intermediate container 66a7bb885da8
     ---> 2f2b89bf850c
    Step 4/5 : ENTRYPOINT ["echo", "Hello"]
     ---> Running in 8fd14a3ae197
    Removing intermediate container 8fd14a3ae197
     ---> 4cb474df91b5
    Step 5/5 : CMD ["World"]
     ---> Running in 5b2381e460b9
    Removing intermediate container 5b2381e460b9
     ---> b26e8bcc53aa
    Successfully built b26e8bcc53aa
    Successfully tagged test/ubuntu:v1
    $ docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
    test/ubuntu         v1                  b26e8bcc53aa        About a minute ago   72.8MB

    Run test image:

    $ docker run -it test/ubuntu:v1
    Hello World

    At this time, when the container is run directly after the image is built, the ENTRYPOINT instruction is run by default. At this time, the CMD instruction is used as the parameter of the ENTRYPOINT instruction, that is, the running command is echo "Hello World".

    When starting the container, add the – entrypoint command to override the entrypoint command:

    $ docker run -it --entrypoint hostname test/ubuntu:v1 -f

    – entrypoint specifies the command instead of the command line, that is, hostname instead of hostname - F. if you need to add parameters to the commands after – entrypoint, the parameters are placed at the end of docker run.


  • ENV baidu ""
    ENV baidu=""
  • The function is to set the environment variable. Other instructions after the ENC instruction, such as RUN, or applications can access the environment variable defined here.

  • Dockerfile file:

    FROM ubuntu
    ENV c curl
    RUN apt-get update && apt-get -y install $c
    CMD ["curl", ""]

    To build a mirror:

    $ docker build -t test/ubuntu:v1 .
    Sending build context to Docker daemon  2.048kB
    Step 1/5 : FROM ubuntu
     ---> ba6acccedd29
    Step 2/5 : MAINTAINER klw
     ---> Running in 8d0cc79cad40
    Removing intermediate container 8d0cc79cad40
     ---> 1b122061de5d
    Step 3/5 : ENV c curl
     ---> Running in 5c889cfc2b9f
    Removing intermediate container 5c889cfc2b9f
     ---> f9c354eb3023
    Step 4/5 : RUN apt-get update && apt-get -y install $c
     ---> Running in 2b3c1e2fd480
    Get:1 focal-security InRelease [114 kB]
    Get:2 focal InRelease [265 kB]
    Unpacking curl (7.68.0-1ubuntu2.7)
    Removing intermediate container 2b3c1e2fd480
     ---> 1db52424a5ff
    Step 5/5 : CMD ["curl", ""]
     ---> Running in dabb0264466d
    Removing intermediate container dabb0264466d
     ---> 38c76ce0b788
    Successfully built 38c76ce0b788
    Successfully tagged test/ubuntu:v1

    It can be seen that the RUN instruction recognizes the set environment variable ENV c curl at runtime.

    Start container:

    $ docker run -it --rm --name test test/ubuntu:v1
    <!DOCTYPE html>
    <!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1. bdstatic. com/r/www/cache/bdorz/baidu. Min.css > < title > Baidu, you will know < / Title > < / head > < body link = #0000cc > < div id = wrapper > < div id = head > < div class = head_ wrapper> <div class=s_ form> <div class=s_ form_ wrapper> <div id=lg> <img hidefocus=true src=// com/img/bd_ logo1. png width=270 height=129> </div> <form id=form name=f action=// com/s class=fm> <input type=hidden name=bdorz_ come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_ bp value=1> <input type=hidden name=rsv_ idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ IPT value MaxLength = 255 autocomplete = off autofocus > < / span > < span class = "BG s_btn_wr" > < input type = submit id = Su value = Baidu class = "BG s_btn" > < / span > < / form > < / div > < div id = U1 > < a href=  name=tj_ Trnews class = mnav > News < / a > < a href=  name=tj_ trhao123 class=mnav>hao123</a> <a href=  name=tj_ TRMAP class = mnav > map < / a > < a href=  name=tj_ Trvideo class = mnav > Video < / a > < a href=  name=tj_ Trtieba class = mnav > Post Bar < / a > < noscript > < a href= ; tpl=mn& u=http%3A%2F%2Fwww. baidu. com%2f%3fbdorz_ come%3d1 name=tj_ Login class = LB > log in to < / a > < / noscript > < script > document write('<a href=" '+ encodeURIComponent(window.location.href+ ( === "" ? "?" :  "&")+ "bdorz_come=1")+ '" name="tj_ Login "class =" LB "> login < / a > '; < / script > < a href = / / COM / more / name = tj_briicon class = bri style =" display: block; "> more products < / a > < / div > < / div > < / div > < div id = ftcon > < div id = ftconw > < p id = LH > < a href= >About Baidu < / a > < a href= >About Baidu</a> </p> <p id=cp>© 2017  Baidu < a href= >Must read < / a > & nbsp; before using Baidu< a href= Class = CP feedback > feedback < / a > & nbsp; Beijing ICP Certificate No. 030173 & nbsp< img src=// com/img/gs. gif> </p> </div> </div> </div> </body> </html>


  • The same function as ENV is to set environment variables, but the environment variables set by ARG are only valid in Dockfile, that is, they take effect during the running of docker build command.

  • ARG baidu ""


  • The function is to define the anonymous data volume. If you forget to mount the data volume when starting the container, it will be automatically mounted to the anonymous data volume.

  • When the container is running, try to keep the container storage layer from writing. For applications where the database class needs to save dynamic data, the database file should be saved in VOLUME. In order to prevent forgetting to mount the data VOLUME when starting the container, you can use VOLUME in Dockerfile to set some paths as the default anonymous data VOLUME. Even if the data VOLUME is not specified when starting the container, it will not be affected and a large amount of data will not be written to the storage layer of the container.

  • Format:

    VOLUME <route>
    VOLUME ["Path 1", "Path 2"]


  • The function is to expose the port

  • Export is just a declaration, which indicates the port through which the container provides services to the external network. The container runtime will not open the services of this port because of this declaration. If you need to EXPOSE the port specified by the export to the outside world, you can specify the port of the container to be exposed to the host in docker run - P < host port >: < container port >. At this time, you can access the service of the container through this port.

  • Advantages: 1 It is convenient for image developers to understand the port guarded by the image service;

    ‚Äč 2. In docker run -P, the export port will be mapped to the host.

  • Format:

    EXPOSE <Port 1> [<Port 2>...]
  • Distinguish between EXPOSE and runtime - p < host port >: < mirror port >, - p maps the container port and the host port, that is, exposes the port corresponding to the container to the outside world, and EXPOSE only declares that the mirror service intends to use this port as the port of the mirror service, and will not automatically map it on the host.


  • The function is to specify the working directory.

  • Use the WORKDIR instruction to specify the working directory, or the current directory. In the future, the working directory of each layer will be changed to the directory specified by the instruction. If the directory does not exist, WORKDIR will establish this directory.

  • The writing of Dockerfile is different from the shell. When the shell runs, all statements in the script are executed in the same process environment, and the statements affect each other; In Dockerfile, each line of instruction is executed by a separate container (the essence of the container is a process). Each line of instruction only changes the current process. The memory of a new container (process) modified by the next line of instruction has nothing to do with the container (process) of the previous instruction.

    Incorrect wording:

    #At this time, in container 1 (process 1), the RUN instruction modifies the working directory change in container 1
    RUN cd /app
    #At this time, in a new container 2 (process 2), the working directory change of the previous level will not be inherited
    RUN echo "test" > test.txt

    Correct writing:

    #Now in container 1
    WORKDIR /app
    #At this time, in container 2, since WORKDIR has specified the working directory, the RUN instruction runs in the / app path.
    RUN echo "test" > test.txt
  • If the WORKDIR uses a relative path, the switched path is related to the previous WORKDIR:

    WORKDIR /app
    RUN pwd

    The working directory of RUN pwd is / app/b/c


  • Format:

    USER <user name>[:<User group>]
  • The function is similar to that of WORKDIR, but WORKDIR is the working directory of the changed layer, and USER is the executor of the changed layer instructions.

  • If you need to switch from root user to other users during instruction execution, do not use sudo su, because it requires cumbersome configuration. It is recommended to use gosu:

    # Download gosu
    RUN wget -O /usr/local/bin/gosu "" \
        && chmod +x /usr/local/bin/gosu \
        && gosu nobody true


  • Format:

    #If the basic image FROM has health check instructions, you can use this line to mask the health check instructions of the basic image
    #Instructions for setting up container health checks
    HEALTHCHECK [option] CMD <command>

    option has three items:

    • --Interval = < time interval >: the time interval between two health checks. The default is 30s.
    • --Retries = < times >: after a specified number of consecutive failures, the container status is determined as unhealthy, and the default number is 3 times.
    • --Timeout = < duration >: the timeout time of the health check instruction. If the health check instruction takes longer than this time, the health check will be regarded as a failure, and the default duration is 30s.

    CMD is followed by the health check command, and the return value is: 0; 1. Unhealthy; 2 keep, do not use this value.

  • The function is to tell the instruction of container health inspection, which is used to judge whether the container is in normal operation.

  • After a health check instruction is formulated for an image, start the container with this image. The initial state of the container is starting. If the health check instruction passes, the container state changes to health; After a specified number of consecutive failures, the container state changes to un healthy.


  • Format:

    ONBUILd <Other instructions>

    For example, onbuild run APR get update & & apt get insatll curl

  • The ONBUILD instruction does not take effect in the process of building an image using the Dockerfile in which it is located, but in the process of building an image based on the image built by the Dockerfile.


  • Format:

    LABEL <key>=<value>
  • LABEL is used to add some metadata to the image in the form of key value pairs, such as adding author information to the image:

    LABEL org.opencontainers.image.authors="test-user"


  • Format:

    SHELL ["bin/sh", "-c"]

    In Linux, the SHELL instruction defaults to ["bin/sh", "-c"]

  • The function is to specify the shell to run in the run CMD enrtypoint instruction shell mode.

Keywords: Docker Ubuntu Container

Added by dc2_jspec on Mon, 03 Jan 2022 20:19:50 +0200