Docker generates an image by reading the dockerfile file. Dockerfile is a text file that contains all commands required by users to build images. After docker build , Docker automatically builds images through a series of command line operations. This article describes the commands in dockerfile.
Usage of Dockerfile
The docker build command uses the Dockerfile file and builds the context of the image. The context can be a local directory or a git repository url. The recognition of context is recursive. Therefore, when specifying a local directory, all subdirectories will be automatically included. When specifying git url, all sub modules of the warehouse will also be automatically included. The following command indicates that the current directory (.) is used as the context environment.
docker build .
Building an image is performed by the docker daemon, not the client. The build process first sends the entire context to the docker daemon. Therefore, it's best to specify the context environment directory to contain only the files and Dockerfile files required to build the image. (it is not recommended to use the / root directory as the context environment, otherwise the files on the entire local disk will be sent to the docker daemon).
Unnecessary contents in the context can be added to the. Docker ignore file. The docker client will not send the file declared by the. Docker ignore file to the docker daemon
By default, the Dockerfile file name is "Dockerfile" and is placed in the first level directory of the context environment. You can also specify other locations with the - f parameter
docker build -f /path/to/a/Dockerfile .
Use - t to specify the warehouse name and tag of the image
docker build -t shykes/myapp .
The same image can be assigned to multiple warehouses with multiple - t
docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .
Docker uses build cache to speed up the build process, and CACHED is displayed in the build process
docker build -t svendowideit/ambassador . [internal] load build definition from Dockerfile 0.1s => transferring dockerfile: 286B 0.0s [internal] load .dockerignore 0.1s => transferring context: 2B 0.0s [internal] load metadata for docker.io/library/alpine:3.2 0.4s CACHED [1/2] FROM docker.io/library/alpine:3.2@sha256:e9a2035f9d0d7ce 0.0s CACHED [2/2] RUN apk add --no-cache socat 0.0s exporting to image 0.0s => exporting layers 0.0s => writing image sha256:1affb80ca37018ac12067fa2af38cc5bcc2a8f09963de 0.0s => naming to docker.io/svendowideit/ambassador 0.0s
The cache is based on the process you built last time-- Cache from allows you to specify an external cache.
Escape character declaration
format
# escape=\ (backslash)
perhaps
# escape=` (backtick)
It is not required. It must be placed on the first line and begin with #
The default escape character is \. The command is too long to write in one line. You can write it like this
RUN echo "import os" >> /root/.jupyter/jupyter_server_config.py \ && echo "c.ServerApp.token = ''" >> /root/.jupyter/jupyter_server_config.py \ && echo "c.ServerApp.password = ''" >> /root/.jupyter/jupyter_server_config.py \
Specifying escape as another character is easier to use on windows because \ is the file path separator on windows. Using other characters can avoid unnecessary trouble.
# escape=` FROM microsoft/nanoserver COPY testfile.txt c:\ RUN dir c:\
Note: it can only be placed on the first line, usually followed by a blank line, and declared before FROM. Otherwise, it will be considered as a comment and will not take effect. Except for this statement, all other # beginning in Dockerfile are regarded as comments.
FROM
FROM [--platform=<platform>] <image> [AS <name>]
Specify the basic image, and subsequent builds are generated based on this basic image. A Dockerfile can have multiple FROM to generate multiple images.
--Platform optional parameter, used to specify the build platform, such as linux/amd64, linux/arm64, windows/amd64
The ARG instruction is the only instruction that can be declared before FROM.
ARG CODE_VERSION=latest FROM base:${CODE_VERSION} CMD /code/run-app FROM extras:${CODE_VERSION} CMD /code/run-extras
RUN
RUN <command>
Shell format, execute the shell command, and the default is / bin/sh -c of linux, cmd /S /C for Windows
The following two commands have the same effect
RUN /bin/bash -c 'source $HOME/.bashrc; \ echo $HOME'
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'
You can also use the following format
RUN ["executable", "param1", "param2"]
for example
RUN ["/bin/bash", "-c", "echo hello"]
Command parameters are passed in json format
CMD
Three forms
- CMD ["executable","param1","param2"] exec format, up to
- CMD ["param1","param2"] As the default parameter of the ENTRYPOINT command
- CMD command param1 param2 shell format
There can only be one CMD in Dockerfile. If more than one CMD is written, only the last one will take effect.
The main purpose of CMD is to provide default commands for container operation. You can also use ENTRYPOINT for container operation. At this time, CMD is used as the parameter of ENTRYPOINT, and both of them should use json format.
The exec format will not call the shell. CMD ["echo", "$home"] is wrong. Either it is in the sehll format: CMD echo $HOME, or use: CMD ["sh", "- C", "echo $home"].
If you use a shell, the command / bin/sh -c execute
FROM ubuntu CMD echo "This is a test." | wc -
If you do not use a shell, you must specify the full path of the command in json format. This method is more common
FROM ubuntu CMD ["/usr/bin/wc","--help"]
If the user specifies other commands when executing docker run, CMD will be overwritten.
Don't confuse RUN with CMD. RUN is actually executed during the mirroring process and submitted to the execution result. CMD does not execute the image, but only assigns a command to the image. The actual execution is when the image is started.
LABEL
LABEL <key>=<value> <key>=<value> <key>=<value> ...
LABEL adds metadata information to the image. The format is key value pair, and an image can contain multiple labels
LABEL "com.example.vendor"="ACME Incorporated" LABEL com.example.label-with-value="foo" LABEL version="1.0" LABEL description="This text illustrates \ that label-values can span multiple lines."
Label can inherit from the basic image. For the same label, the latest assignment will overwrite the previous one.
Through docker image inspect -- format='' myimage can view the mirrored labels
docker image inspect --format='' myimage
result:
{ "com.example.vendor": "ACME Incorporated", "com.example.label-with-value": "foo", "version": "1.0", "description": "This text illustrates that label-values can span multiple lines.", "multi.label1": "value1", "multi.label2": "value2", "other": "value3" }
MAINTAINER (deprecated)
Specify the mirror author, The new version is no longer recommended. It is officially recommended to use LABEL instead. for example
LABEL org.opencontainers.image.authors="SvenDowideit@home.org.au"
EXPOSE
EXPOSE <port> [<port>/<protocol>...]
Tell Docker which port the container will listen on. Specify TCP or UDP. The default is TCP.
Expo will not really publish this port. It is actually a description provided by the person building the image to the person running the image. The real exposed port is to map the host port to the container port when docker run s through the - P or - P parameter.
docker run -p 80:80/tcp -p 80:80/udp ...
Network communication between containers can be carried out using docker network related instructions without exposing to the host.
ENV
ENV <key>=<value> ...
Setting environment variables allows multiple environment variables to be set after the same ENV
ENV MY_NAME="John Doe" MY_DOG=Rex\ The\ Dog \ MY_CAT=fluffy
If an environment variable only needs to be used when creating an image without assigning a value to the final image, it can be specified in a single instruction
RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y ...
Or ARG will not be assigned to the final image
ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y ...
Another format is not =, which can only define one variable at a time
ENV MY_VAR my-value
ADD
ADD [--chown=<user>:<group>] <src>... <dest> ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
-- chown optional parameter. Only linux containers are supported
src can be a file or URL in the context. Wildcards can be used in src, such as
ADD hom* /mydir/
All files starting with hom will be added to / mydir /.
If dest is a relative path, it is the relative path of WORKDIR
add to "test.txt" to < WORKDIR>/relativeDir/ :
ADD test.txt relativeDir/
Add "test.txt" to / absoluteDir/ :
ADD test.txt /absoluteDir/
Notes:
- The < SRC > path must be a file in the context
- If < SRC > is a url, < dest > does not end with a backslash, and the file is renamed to the value of < dest > after being downloaded
- If < SRC > is a url and < dest > ends with a backslash, the file is downloaded as / < dest > / < filename >
- If < SRC > is a directory, all files in the directory will be copied, including file meta information. Note that the directory itself will not be copied, only the contents of the directory will be copied
- If < SRC > is a compressed package, it will be automatically decompressed when copying. The compressed package in the URL will not be decompressed.
- < dest > if it does not end with a backslash, it will be recognized as a file, and the copied source file will be renamed as < dest >. If it ends with a backslash, it will be considered as a directory, and the original file will be copied to the < dest > directory
- If the path contained in < dest > does not exist, it will be automatically created
COPY
COPY [--chown=<user>:<group>] <src>... <dest> COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]
The function of copying files is the same as ADD. You cannot automatically decompress the compressed package and copy the URL
There is an optional parameter -- from = < name >, which can take the previously constructed step as the original file location (from.. as < name >)
In the COPY and ADD commands, if the source file is modified, the subsequent command cache will become invalid from COPY or ADD
ENTRYPOINT
exec format
ENTRYPOINT ["executable", "param1", "param2"]
shell format
ENTRYPOINT command param1 param2
When docker run < Image >, the parameters passed in will be passed to ENTRYPOINT and will overwrite CMD. For example, the - d parameter of docker run < Image > - d command will be passed to entry point. docker run --entrypoint Overrides the ENTRYPOINT command.
shell format entrypoint does not accept parameters passed by CMD or run.
Only the last entry point in Dockerfile will take effect.
Relationship between CMD and ENTRYPOINT
- Dockerfile should contain at least one of CMD and ENTRYPOINT
- CMD should be used as the default parameter of ENTRYPOINT and can be overridden at run time
The following table shows the final commands executed after different CMD and ENTRYPOINT combinations
VOLUME
VOLUME ["/data"]
VOLUME /data
Create a directory that can be mounted to the container from the local machine
for example
FROM ubuntu RUN mkdir /myvol RUN echo "hello world" > /myvol/greeting VOLUME /myvol
be careful:
- When using the windows based container, the mounted directory must be an empty directory and cannot be disk C
- The directory declared by volume and subsequent modifications to this directory in Dockerfile will be invalid
- json format declaration must be in double quotation marks, not single quotation marks
- The mounted host directory can only be specified at run time
USER
USER <user>[:<group>]
USER <UID>[:<GID>]
Optionally, specify the users and user groups that build the mirror runtime
If it is a windows image, you must first create a user
FROM microsoft/windowsservercore # Create Windows user in the container RUN net user /add patrick # Set it for subsequent commands USER patrick
WORKDIR
WORKDIR /path/to/workdir
Specify the working directory for all RUN, CMD, ENTRYPOINT, ADD commands
You can specify multiple times. If it is a relative directory, the last value is the first pair directory of the previous WORKDIR, such as
WORKDIR /a WORKDIR b WORKDIR c RUN pwd
Output as / a/b/c
You can use environment variable definitions, such as
ENV DIRPATH=/path WORKDIR $DIRPATH/$DIRNAME RUN pwd
Output as / path/$DIRNAME
ARG
ARG <name>[=<default value>]
Specify an environment variable during mirroring, docker build -- build Arg < Varname > = < value >
FROM busybox ARG user1 ARG buildno # ...
Specify default values
FROM busybox ARG user1=someuser ARG buildno=1 # ...
Scope of ARG
ARG takes effect from the line where the declaration begins, not the line used, for example
FROM busybox USER ${user:-some_user} ARG user USER $user # ...
implement
docker build --build-arg user=what_user .
The USER value in the second line is some_user, the USER value in the fourth line is what_user
The ARG declared in a construction phase only takes effect in this phase. If multiple phases are required, each phase must be declared, as follows:
FROM busybox ARG SETTINGS RUN ./run/setup $SETTINGS FROM busybox ARG SETTINGS RUN ./run/other $SETTINGS
Predefined ARG
- HTTP_PROXY
- http_proxy
- HTTPS_PROXY
- https_proxy
- FTP_PROXY
- ftp_proxy
- NO_PROXY
- no_proxy
use
docker build --build-arg HTTPS_PROXY=https://my-proxy.example.com .
OBBUILD
ONBUILD <INSTRUCTION>
STOPSIGNAL
STOPSIGNAL signal
HEALTHCHECK
HEALTHCHECK [OPTIONS] CMD command
HEALTHCHECK NONE
SHELL
SHELL ["executable", "parameters"]