Docker
Dockerfile
I like to call Dockerfile the predecessor of a container image. You build an image from a Dockerfile. A typical Dockerfile contains special build instructions, commands like RUN
, ADD
, COPY
, ENTRYPOINT
, etc.
Usage
-
The docker build command builds an image from a
Dockerfile
and a context. The build’s context is the set of files at a specified locationPATH
orURL
. ThePATH
is a directory on your local filesystem. TheURL
is a Git repository location. -
To use a file in the build context, the
Dockerfile
refers to the file specified in an instruction, for example, aCOPY
instruction. To increase the build’s performance, exclude files and directories by adding a.dockerignore
file to the context directory. For information about how to create a.dockerignore
file see the documentation on this page. -
You use the
-f
flag withdocker build
to point to a Dockerfile anywhere in your file system.docker build -f /path/to/a/Dockerfile .
-
You can specify a repository and tag at which to save the new image if the build succeeds:
docker build -t shykes/myapp .
-
Note that each instruction is run independently, and causes a new image to be created - so
RUN cd /tmp
will not have any effect on the next instructions. -
Whenever possible, Docker uses a build-cache to accelerate the
docker build
process significantly. This is indicated by theCACHED
message in the console output. (For more information, see theDockerfile
best practices guide):
BuildKit Project
Starting with version 18.09, Docker supports a new backend for executing your builds that is provided by the moby/buildkit project. The BuildKit backend provides many benefits compared to the old implementation. For example, BuildKit can:
- Detect and skip executing unused build stages
- Parallelize building independent build stages
- Incrementally transfer only the changed files in your build context between builds
- Detect and skip transferring unused files in your build context
- Use external Dockerfile implementations with many new features
- Avoid side-effects with rest of the API (intermediate images and containers)
- Prioritize your build cache for automatic pruning
To use the BuildKit backend, you need to set an environment variable DOCKER_BUILDKIT=1
on the CLI before invoking docker build
.
To learn about the Dockerfile syntax available to BuildKit-based builds refer to the documentation in the BuildKit repository.
Format
- Docker runs instructions in a
Dockerfile
in order. ADockerfile
must begin with aFROM
instruction. This may be after parser directives, comments, and globally scoped ARGs. TheFROM
instruction specifies the Parent Image from which you are building.FROM
may only be preceded by one or more instructionsARG
, which declare arguments that are used inFROM
lines in theDockerfile
.
Parser directives
-
Parser directives are optional, and affect the way in which subsequent lines in a
Dockerfile
are handled. Parser directives do not add layers to the build, and will not be shown as a build step. Parser directives are written as a special type of comment in the form# directive=value
. A single directive may only be used once. -
Once a comment, empty line or builder instruction has been processed, Docker no longer looks for parser directives. Instead it treats anything formatted as a parser directive as a comment and does not attempt to validate if it might be a parser directive. Therefore, all parser directives must be at the very top of a
Dockerfile
.Parser directives are not case-sensitive. However, convention is for them to be lowercase. Convention is also to include a blank line following any parser directives. Line continuation characters are not supported in parser directives.
-
invalid examples:
-
Invalid due to line continuation:
# direc \
tive=value -
Invalid due to appearing twice:
# directive=value1
# directive=value2
FROM ImageName -
Treated as a comment due to appearing after a builder instruction:
FROM ImageName
# directive=value -
Treated as a comment due to appearing after a comment which is not a parser directive:
# About my dockerfile
# directive=value
FROM ImageName -
The unknown directive is treated as a comment due to not being recognized. In addition, the known directive is treated as a comment due to appearing after a comment which is not a parser directive.
# unknowndirective=value
# knowndirective=value -
The following parser directives are supported:
syntax
escape
-
-
syntax
# syntax=[remote image reference]
-
for example
# syntax=docker/dockerfile:1
# syntax=docker.io/docker/dockerfile:1
# syntax=example.com/user/repo:tag@sha256:abcdef... -
This feature is only available when using the BuildKit backend, and is ignored when using the classic builder backend.
The syntax directive defines the location of the Dockerfile syntax that is used to build the Dockerfile. The BuildKit backend allows to seamlessly use external implementations that are distributed as Docker images and execute inside a container sandbox environment.
-
Official releases
Docker distributes official versions of the images that can be used for building Dockerfiles under
docker/dockerfile
repository on Docker Hub. There are two channels where new images are released:stable
andlabs
.Stable channel follows semantic versioning. For example:
docker/dockerfile:1
- kept updated with the latest1.x.x
minor and patch releasedocker/dockerfile:1.2
- kept updated with the latest1.2.x
patch release, and stops receiving updates once version1.3.0
is released.docker/dockerfile:1.2.1
- immutable: never updated
We recommend using
docker/dockerfile:1
, which always points to the latest stable release of the version 1 syntax, and receives both “minor” and “patch” updates for the version 1 release cycle. BuildKit automatically checks for updates of the syntax when performing a build, making sure you are using the most current version. -
labs channel
The “labs” channel provides early access to Dockerfile features that are not yet available in the stable channel. Labs channel images are released in conjunction with the stable releases, and follow the same versioning with the
-labs
suffix, for example:docker/dockerfile:labs
- latest release on labs channeldocker/dockerfile:1-labs
- same asdockerfile:1
in the stable channel, with labs features enableddocker/dockerfile:1.2-labs
- same asdockerfile:1.2
in the stable channel, with labs features enableddocker/dockerfile:1.2.1-labs
- immutable: never updated. Same asdockerfile:1.2.1
in the stable channel, with labs features enabled
-
-
escape
# escape=\ (backslash)
Or
# escape=` (backtick)
-
The
escape
directive sets the character used to escape characters in aDockerfile
. If not specified, the default escape character is\
.The escape character is used both to escape characters in a line, and to escape a newline. This allows a
Dockerfile
instruction to span multiple lines. Note that regardless of whether theescape
parser directive is included in aDockerfile
, escaping is not performed in aRUN
command, except at the end of a line.Setting the escape character to
is especially useful on `Windows`, where `\` is the directory path separator.
is consistent with Windows PowerShell. -
example
FROM microsoft/nanoserver
COPY testfile.txt c:\\
RUN dir c:\result as:
-
Environment replacement🔗
- Environment variables (declared with the
ENV
statement) can also be used in certain instructions as variables to be interpreted by theDockerfile
. Escapes are also handled for including variable-like syntax into a statement literally. - The
${variable_name}
syntax also supports a few of the standardbash
modifiers as specified below:${variable:-word}
indicates that ifvariable
is set then the result will be that value. Ifvariable
is not set thenword
will be the result.${variable:+word}
indicates that ifvariable
is set thenword
will be the result, otherwise the result is the empty string.
- Environment variables are supported by the following list of instructions in the
Dockerfile
:ADD
COPY
ENV
EXPOSE
FROM
LABEL
STOPSIGNAL
USER
VOLUME
WORKDIR
ONBUILD
(when combined with one of the supported instructions above)
.dockerignore file
- Before the docker CLI sends the context to the docker daemon, it looks for a file named
.dockerignore
in the root directory of the context. If this file exists, the CLI modifies the context to exclude files and directories that match patterns in it. This helps to avoid unnecessarily sending large or sensitive files and directories to the daemon and potentially adding them to images usingADD
orCOPY
.
FROM
FROM [--platform=<platform>] <image> [AS <name>] |
Or
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>] |
Or
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>] |
The FROM
instruction initializes a new build stage and sets the Base Image for subsequent instructions. As such, a valid Dockerfile
must start with a FROM
instruction. The image can be any valid image – it is especially easy to start by pulling an image from the Public Repositories.
- `ARG` is the only instruction that may precede `FROM` in the `Dockerfile`. See [Understand how ARG and FROM interact](https://docs.docker.com/engine/reference/builder/#understand-how-arg-and-from-interact).
-
FROM
can appear multiple times within a singleDockerfile
to create multiple images or use one build stage as a dependency for another. Simply make a note of the last image ID output by the commit before each newFROM
instruction. EachFROM
instruction clears any state created by previous instructions. -
Optionally a name can be given to a new build stage by adding
AS name
to theFROM
instruction. The name can be used in subsequentFROM
andCOPY --from=<name>
instructions to refer to the image built in this stage. -
The
tag
ordigest
values are optional. If you omit either of them, the builder assumes alatest
tag by default. The builder returns an error if it cannot find thetag
value. -
The optional
--platform
flag can be used to specify the platform of the image in caseFROM
references a multi-platform image. For example,linux/amd64
,linux/arm64
, orwindows/amd64
. By default, the target platform of the build request is used. Global build arguments can be used in the value of this flag, for example automatic platform ARGs allow you to force a stage to native build platform (), and use it to cross-compile to the target platform inside the stage.--platform=$BUILDPLATFORM
RUN
RUN has 2 forms:
-
RUN <command>
(shell form, the command is run in a shell, which by default is/bin/sh -c
on Linux orcmd /S /C
on Windows) -
RUN ["executable", "param1", "param2"]
(exec form)-
The exec form makes it possible to avoid shell string munging, and to
RUN
commands using a base image that does not contain the specified shell executable. -
To use a different shell, other than ‘/bin/sh’, use the exec form passing in the desired shell. For example:
RUN ["/bin/bash", "-c", "echo hello"]
-
Note:The exec form is parsed as a JSON array, which means that you must use double-quotes (“) around words not single-quotes (‘).
-
-
KWOWN ISSUE
-
Issue 783 is about file permissions problems that can occur when using the AUFS file system. You might notice it during an attempt to
rm
a file, for example.For systems that have recent aufs version (i.e.,
dirperm1
mount option can be set), docker will attempt to fix the issue automatically by mounting the layers withdirperm1
option. More details ondirperm1
option can be found ataufs
man pageIf your system doesn’t have support for
dirperm1
, the issue describes a workaround.
-
CMD
The CMD
instruction has three forms:
-
CMD ["executable","param1","param2"]
(exec form, this is the preferred form) -
CMD ["param1","param2"]
(as default parameters to ENTRYPOINT) -
CMD command param1 param2
(shell form) -
There can only be one
CMD
instruction in aDockerfile
. If you list more than oneCMD
then only the lastCMD
will take effect.The main purpose of a
CMD
is to provide defaults for an executing container. These defaults can include an executable, or they can omit the executable, in which case you must specify anENTRYPOINT
instruction as well.If
CMD
is used to provide default arguments for theENTRYPOINT
instruction, both theCMD
andENTRYPOINT
instructions should be specified with the JSON array format. -
If the user specifies arguments to
docker run
then they will override the default specified inCMD
. -
Note:Do not confuse
RUN
withCMD
.RUN
actually runs a command and commits the result;CMD
does not execute anything at build time, but specifies the intended command for the image.
LABEL
LABEL <key>=<value> <key>=<value> <key>=<value> ... |
The LABEL
instruction adds metadata to an image. A LABEL
is a key-value pair. To include spaces within a LABEL
value, use quotes and backslashes as you would in command-line parsing. A few usage examples:
LABEL "com.example.vendor"="ACME Incorporated" |
-
An image can have more than one label. You can specify multiple labels on a single line. Prior to Docker 1.10, this decreased the size of the final image, but this is no longer the case. You may still choose to specify multiple labels in a single instruction, in one of the following two ways:
LABEL multi.label1="value1" multi.label2="value2" other="value3"
LABEL multi.label1="value1" \
multi.label2="value2" \
other="value3" -
Labels included in base or parent images (images in the
FROM
line) are inherited by your image. If a label already exists but with a different value, the most-recently-applied value overrides any previously-set value.To view an image’s labels, use the
docker image inspect
command. You can use the--format
option to show just the labels;docker image inspect --format='' myimage
EXPOSE
EXPOSE <port> [<port>/<protocol>...] |
The EXPOSE
instruction informs Docker that the container listens on the specified network ports at runtime. You can specify whether the port listens on TCP or UDP, and the default is TCP if the protocol is not specified.
The EXPOSE
instruction does not actually publish the port. It functions as a type of documentation between the person who builds the image and the person who runs the container, about which ports are intended to be published. To actually publish the port when running the container, use the -p
flag on docker run
to publish and map one or more ports, or the -P
flag to publish all exposed ports and map them to high-order ports.
By default, EXPOSE
assumes TCP. You can also specify UDP:
To expose on both TCP and UDP, include two lines:
EXPOSE 80/tcp |
To set up port redirection on the host system, see using the -P flag. The docker network
command supports creating networks for communication among containers without the need to expose or publish specific ports, because the containers connected to the network can communicate with each other over any port. For detailed information, see the overview of this feature.
Dcoker Network overview
Network drivers
bridge
: The default network driver. If you don’t specify a driver, this is the type of network you are creating. Bridge networks are usually used when your applications run in standalone containers that need to communicate. See bridge networks.host
: For standalone containers, remove network isolation between the container and the Docker host, and use the host’s networking directly. See use the host network.overlay
: Overlay networks connect multiple Docker daemons together and enable swarm services to communicate with each other. You can also use overlay networks to facilitate communication between a swarm service and a standalone container, or between two standalone containers on different Docker daemons. This strategy removes the need to do OS-level routing between these containers. See overlay networks.ipvlan
: IPvlan networks give users total control over both IPv4 and IPv6 addressing. The VLAN driver builds on top of that in giving operators complete control of layer 2 VLAN tagging and even IPvlan L3 routing for users interested in underlay network integration. See IPvlan networks.macvlan
: Macvlan networks allow you to assign a MAC address to a container, making it appear as a physical device on your network. The Docker daemon routes traffic to containers by their MAC addresses. Using themacvlan
driver is sometimes the best choice when dealing with legacy applications that expect to be directly connected to the physical network, rather than routed through the Docker host’s network stack. See Macvlan networks.none
: For this container, disable all networking. Usually used in conjunction with a custom network driver.none
is not available for swarm services. See disable container networking.- Network driver summary
- User-defined bridge networks are best when you need multiple containers to communicate on the same Docker host.
- Host networks are best when the network stack should not be isolated from the Docker host, but you want other aspects of the container to be isolated.
- Overlay networks are best when you need containers running on different Docker hosts to communicate, or when multiple applications work together using swarm services.
- Macvlan networks are best when you are migrating from a VM setup or need your containers to look like physical hosts on your network, each with a unique MAC address.
- Third-party network plugins allow you to integrate Docker with specialized network stacks.
ENV
Docker automatically sets some environment variables when creating a Linux container. Docker does not set any environment variables when creating a Windows container.
The following environment variables are set for Linux containers:
Variable | Value |
---|---|
HOME |
Set based on the value of USER |
HOSTNAME |
The hostname associated with the container |
PATH |
Includes popular directories, such as /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin |
TERM |
xterm if the container is allocated a pseudo-TTY |
Additionally, the operator can set any environment variable in the container by using one or more -e
flags, even overriding those mentioned above, or already defined by the developer with a Dockerfile ENV
. If the operator names an environment variable without specifying a value, then the current value of the named variable is propagated into the container’s environment:
The environment variables set using ENV
will persist when a container is run from the resulting image. You can view the values using docker inspect
, and change them using docker run --env <key>=<value>
.
ADD/COPY
ADD/COPY has two forms:
ADD [--chown=<user>:<group>] <src>... <dest> |
-
Note:The
--chown
feature is only supported on Dockerfiles used to build Linux containers, and will not work on Windows containers. Since user and group ownership concepts do not translate between Linux and Windows, the use of/etc/passwd
and/etc/group
for translating user and group names to IDs restricts this feature to only be viable for Linux OS-based containers. -
Effect:
- The
ADD
instruction copies new files, directories or remote file URLs from<src>
and adds them to the filesystem of the image at the path<dest>
. - The
COPY
instruction copies new files or directories from<src>
and adds them to the filesystem of the container at the path<dest>
.
- The
-
The
<dest>
is an absolute path, or a path relative toWORKDIR
, into which the source will be copied inside the destination container.The example below uses a relative path, and adds “test.txt” to
<WORKDIR>/relativeDir/
:ADD test.txt relativeDir/
Whereas this example uses an absolute path, and adds “test.txt” to
/absoluteDir/
ADD test.txt /absoluteDir/
-
All new files and directories are created with a UID and GID of 0, unless the optional
--chown
flag specifies a given username, groupname, or UID/GID combination to request specific ownership of the content added. If a username or groupname is provided, the container’s root filesystem/etc/passwd
and/etc/group
files will be used to perform the translation from name to integer UID or GID respectively.The following examples show valid definitions for the--chown
flag:ADD --chown=55:mygroup files* /somedir/
ADD --chown=bin files* /somedir/
ADD --chown=1 files* /somedir/
ADD --chown=10:11 files* /somedir/
COPY --chown=55:mygroup files* /somedir/
COPY --chown=bin files* /somedir/
COPY --chown=1 files* /somedir/
COPY --chown=10:11 files* /somedir/- If the container root filesystem does not contain either
/etc/passwd
or/etc/group
files and either user or group names are used in the--chown
flag, the build will fail on theADD
operation. Using numeric IDs requires no lookup and will not depend on container root filesystem content. - In the case where
<src>
is a remote file URL, the destination will have permissions of 600. If the remote file being retrieved has an HTTPLast-Modified
header, the timestamp from that header will be used to set themtime
on the destination file. However, like any other file processed during anADD
,mtime
will not be included in the determination of whether or not the file has changed and the cache should be updated. - If your URL files are protected using authentication, you need to use
RUN wget
,RUN curl
or use another tool from within the container as theADD
instruction does not support authentication.
- If the container root filesystem does not contain either
-
Optionally
COPY
accepts a flag--from=<name>
that can be used to set the source location to a previous build stage (created withFROM .. AS <name>
) that will be used instead of a build context sent by the user. In case a build stage with a specified name can’t be found an image with the same name is attempted to be used instead. -
ADD
obeys the following rules:- The
<src>
path must be inside the context of the build; you cannotADD ../something /something
, because the first step of adocker build
is to send the context directory (and subdirectories) to the docker daemon. - If
<src>
is a URL and<dest>
does not end with a trailing slash(/), then a file is downloaded from the URL and copied to<dest>
. - If
<src>
is a URL and<dest>
does end with a trailing slash(/), then the filename is inferred from the URL and the file is downloaded to<dest>/<filename>
. For instance,ADD http://example.com/foobar /
would create the file/foobar
. The URL must have a nontrivial path so that an appropriate filename can be discovered in this case (http://example.com
will not work). - If
<src>
is a directory, the entire contents of the directory are copied, including filesystem metadata. - If
<src>
is a local tar archive in a recognized compression format (identity, gzip, bzip2 or xz) then it is unpacked as a directory. Resources from remote URLs are not decompressed. - f
<src>
is any other kind of file, it is copied individually along with its metadata. In this case, if<dest>
ends with a trailing slash/
, it will be considered a directory and the contents of<src>
will be written at<dest>/base(<src>)
. - If multiple
<src>
resources are specified, either directly or due to the use of a wildcard, then<dest>
must be a directory, and it must end with a slash/
. - If
<dest>
does not end with a trailing slash, it will be considered a regular file and the contents of<src>
will be written at<dest>
. - If
<dest>
doesn’t exist, it is created along with all missing directories in its path.
- The
ENTRYPOINT
The exec form, which is the preferred form:
ENTRYPOINT ["executable", "param1", "param2"] |
The shell form:
ENTRYPOINT command param1 param2 |
Command line arguments to docker run <image>
will be appended after all elements in an exec form ENTRYPOINT
, and will override all elements specified using CMD
. This allows arguments to be passed to the entry point, i.e., docker run <image> -d
will pass the -d
argument to the entry point. You can override the ENTRYPOINT
instruction using the docker run --entrypoint
flag.
The shell form prevents any CMD
or run
command line arguments from being used, but has the disadvantage that your ENTRYPOINT
will be started as a subcommand of /bin/sh -c
, which does not pass signals. This means that the executable will not be the container’s PID 1
- and will not receive Unix signals - so your executable will not receive a SIGTERM
from docker stop <container>
.
Only the last ENTRYPOINT
instruction in the Dockerfile
will have an effect.
Exec form ENTRYPOINT example
You can use the exec form of ENTRYPOINT
to set fairly stable default commands and arguments and then use either form of CMD
to set additional defaults that are more likely to be changed.
FROM ubuntu |
When you run the container, you can see that top
is the only process:
docker run -it --rm --name test top -H |
To examine the result further, you can use docker exec
:
docker exec -it test ps aux |
EXPLAINATION: parameters behind image -H overwrite the parameters in CMD [“-c”]
And you can gracefully request top
to shut down using docker stop test
.
If you need to write a starter script for a single executable, you can ensure that the final executable receives the Unix signals by using exec
and gosu
commands:
- exec: make sure the new executable process will be the PID 1 not the script process
- gosu: tool used to grant entitlement for the command instead of using sudo
#!/usr/bin/env bash |
Shell form ENTRYPOINT example
You can specify a plain string for the ENTRYPOINT
and it will execute in /bin/sh -c
. This form will use shell processing to substitute shell environment variables, and will ignore any CMD
or docker run
command line arguments. To ensure that docker stop
will signal any long running ENTRYPOINT
executable correctly, you need to remember to start it with exec
:
FROM ubuntu |
Understand how CMD and ENTRYPOINT interact
Both CMD
and ENTRYPOINT
instructions define what command gets executed when running a container. There are few rules that describe their co-operation.
- Dockerfile should specify at least one of
CMD
orENTRYPOINT
commands. ENTRYPOINT
should be defined when using the container as an executable.CMD
should be used as a way of defining default arguments for anENTRYPOINT
command or for executing an ad-hoc command in a container.CMD
will be overridden when running the container with alternative arguments.
The table below shows what command is 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 |
VOLUME
VOLUME
VOLUME ["/data"] |
The VOLUME
instruction creates a mount point with the specified name and marks it as holding externally mounted volumes from native host or other containers. The value can be a JSON array, VOLUME ["/var/log/"]
, or a plain string with multiple arguments, such as VOLUME /var/log
or VOLUME /var/log /var/db
. For more information/examples and mounting instructions via the Docker client, refer to Share Directories via Volumes documentation.
The docker run
command initializes the newly created volume with any data that exists at the specified location within the base image. For example, consider the following Dockerfile snippet:
FROM ubuntu |
This Dockerfile results in an image that causes docker run
to create a new mount point at /myvol
and copy the greeting
file into the newly created volume.
-
Notes about specifying volumes
Keep the following things in mind about volumes in the
Dockerfile
.- Volumes on Windows-based containers: When using Windows-based containers, the destination of a volume inside the container must be one of:
- a non-existing or empty directory
- a drive other than
C:
- Changing the volume from within the Dockerfile: If any build steps change the data within the volume after it has been declared, those changes will be discarded.
- JSON formatting: The list is parsed as a JSON array. You must enclose words with double quotes (
"
) rather than single quotes ('
). - The host directory is declared at container run-time: The host directory (the mountpoint) is, by its nature, host-dependent. This is to preserve image portability, since a given host directory can’t be guaranteed to be available on all hosts. For this reason, you can’t mount a host directory from within the Dockerfile. The
VOLUME
instruction does not support specifying ahost-dir
parameter. You must specify the mountpoint when you create or run the container.
- Volumes on Windows-based containers: When using Windows-based containers, the destination of a volume inside the container must be one of:
USER
USER <user>[:<group>] |
or
USER <UID>[:<GID>] |
The USER
instruction sets the user name (or UID) and optionally the user group (or GID) to use when running the image and for any RUN
, CMD
and ENTRYPOINT
instructions that follow it in the Dockerfile
.
WORKDIR
WORKDIR /path/to/workdir |
The WORKDIR
instruction sets the working directory for any RUN
, CMD
, ENTRYPOINT
, COPY
and ADD
instructions that follow it in the Dockerfile
. If the WORKDIR
doesn’t exist, it will be created even if it’s not used in any subsequent Dockerfile
instruction.
The WORKDIR
instruction can be used multiple times in a Dockerfile
. If a relative path is provided, it will be relative to the path of the previous WORKDIR
instruction. For example:
WORKDIR /a |
The output of the final pwd
command in this Dockerfile
would be /a/b/c
.
ARG
ARG <name>[=<default value>] |
The ARG
instruction defines a variable that users can pass at build-time to the builder with the docker build
command using the --build-arg <varname>=<value>
flag. If a user specifies a build argument that was not defined in the Dockerfile, the build outputs a warning.
[Warning] One or more build-args [foo] were not consumed. |
A Dockerfile may include one or more ARG
instructions. For example, the following is a valid Dockerfile:
FROM busybox |
An ARG
instruction goes out of scope at the end of the build stage where it was defined. To use an arg in multiple stages, each stage must include the ARG
instruction.
FROM busybox |
You can use an ARG
or an ENV
instruction to specify variables that are available to the RUN
instruction. Environment variables defined using the ENV
instruction always override an ARG
instruction of the same name. Consider this Dockerfile with an ENV
and ARG
instruction.
FROM ubuntu |
Then, assume this image is built with this command:
$ docker build --build-arg CONT_IMG_VER=v2.0.1 . |
In this case, the RUN
instruction uses v1.0.0
instead of the ARG
setting passed by the user:v2.0.1
Using the example above but a different ENV
specification you can create more useful interactions between ARG
and ENV
instructions:
FROM ubuntu |
Unlike an ARG
instruction, ENV
values are always persisted in the built image. Consider a docker build without the --build-arg
flag:
$ docker build . |
Using this Dockerfile example, CONT_IMG_VER
is still persisted in the image but its value would be v1.0.0
as it is the default set in line 3 by the ENV
instruction.
Predefined ARGs
Docker has a set of predefined ARG
variables that you can use without a corresponding ARG
instruction in the Dockerfile.
HTTP_PROXY
http_proxy
HTTPS_PROXY
https_proxy
FTP_PROXY
ftp_proxy
NO_PROXY
no_proxy
To use these, pass them on the command line using the --build-arg
flag, for example:
$ docker build --build-arg HTTPS_PROXY=https://my-proxy.example.com . |
By default, these pre-defined variables are excluded from the output of docker history
. Excluding them reduces the risk of accidentally leaking sensitive authentication information in an HTTP_PROXY
variable.
ONBUILD
ONBUILD <INSTRUCTION> |
The ONBUILD
instruction adds to the image a trigger instruction to be executed at a later time, when the image is used as the base for another build. The trigger will be executed in the context of the downstream build, as if it had been inserted immediately after the FROM
instruction in the downstream Dockerfile
.
Any build instruction can be registered as a trigger.
This is useful if you are building an image which will be used as a base to build other images, for example an application build environment or a daemon which may be customized with user-specific configuration.
For example, if your image is a reusable Python application builder, it will require application source code to be added in a particular directory, and it might require a build script to be called after that. You can’t just call ADD
and RUN
now, because you don’t yet have access to the application source code, and it will be different for each application build. You could simply provide application developers with a boilerplate to copy-paste into their applicationDockerfile
, but that is inefficient, error-prone and difficult to update because it mixes with application-specific code.
Here’s how it works:
- When it encounters an
ONBUILD
instruction, the builder adds a trigger to the metadata of the image being built. The instruction does not otherwise affect the current build. - At the end of the build, a list of all triggers is stored in the image manifest, under the key
OnBuild
. They can be inspected with thedocker inspect
command. - Later the image may be used as a base for a new build, using the
FROM
instruction. As part of processing theFROM
instruction, the downstream builder looks forONBUILD
triggers, and executes them in the same order they were registered. If any of the triggers fail, theFROM
instruction is aborted which in turn causes the build to fail. If all triggers succeed, theFROM
instruction completes and the build continues as usual. - Triggers are cleared from the final image after being executed. In other words they are not inherited by “grand-children” builds.
For example you might add something like this:
ONBUILD ADD . /app/src |
STOPSIGNAL
STOPSIGNAL signal |
The STOPSIGNAL
instruction sets the system call signal that will be sent to the container to exit. This signal can be a signal name in the format SIG<NAME>
, for instance SIGKILL
, or an unsigned number that matches a position in the kernel’s syscall table, for instance 9
. The default is SIGTERM
if not defined.
The image’s default stopsignal can be overridden per container, using the --stop-signal
flag on docker run
and docker create
.
HEALTHCHECK
The HEALTHCHECK
instruction has two forms:
HEALTHCHECK [OPTIONS] CMD command
(check container health by running a command inside the container)HEALTHCHECK NONE
(disable any healthcheck inherited from the base image)
The HEALTHCHECK
instruction tells Docker how to test a container to check that it is still working. This can detect cases such as a web server that is stuck in an infinite loop and unable to handle new connections, even though the server process is still running.
When a container has a healthcheck specified, it has a health status in addition to its normal status. This status is initially starting
. Whenever a health check passes, it becomes healthy
(whatever state it was previously in). After a certain number of consecutive failures, it becomes unhealthy
.
-
The options that can appear before
CMD
are:-
--interval=DURATION
(default:30s
) -
--timeout=DURATION
(default:30s
) -
--start-period=DURATION
(default:0s
) -
--retries=N
(default:3
)
-
-
EXPLAINATION:
-
The health check will first run interval seconds after the container is started, and then again interval seconds after each previous check completes.
-
If a single run of the check takes longer than timeout seconds then the check is considered to have failed.It takes retries consecutive failures of the health check for the container to be considered
unhealthy
. -
start period provides initialization time for containers that need time to bootstrap. Probe failure during that period will not be counted towards the maximum number of retries. However, if a health check succeeds during the start period, the container is considered started and all consecutive failures will be counted towards the maximum number of retries.
-
-
There can only be one HEALTHCHECK
instruction in a Dockerfile. If you list more than one then only the last HEALTHCHECK
will take effect.
The command’s exit status indicates the health status of the container. The possible values are:
- 0: success - the container is healthy and ready for use
- 1: unhealthy - the container is not working correctly
- 2: reserved - do not use this exit code
For example, to check every five minutes or so that a web-server is able to serve the site’s main page within three seconds:
HEALTHCHECK --interval=5m --timeout=3s \ |
--health-cmd Command to run to check health |
SHELL
SHELL ["executable", "parameters"] |
The SHELL
instruction allows the default shell used for the shell form of commands to be overridden. The default shell on Linux is ["/bin/sh", "-c"]
, and on Windows is ["cmd", "/S", "/C"]
. The SHELL
instruction must be written in JSON form in a Dockerfile.
The SHELL
instruction is particularly useful on Windows where there are two commonly used and quite different native shells: cmd
and powershell
, as well as alternate shells available including sh
.
The SHELL
instruction can appear multiple times. Each SHELL
instruction overrides all previous SHELL
instructions, and affects all subsequent instructions. For example:
FROM microsoft/windowsservercore |
Docker-Compose
Compose specification
The Compose file is a YAML file defining services, networks, and volumes for a Docker application. The latest and recommended version of the Compose file format is defined by the Compose Specification
The Compose application model
- SERVICE
- Computing components of an application are defined as Services. A Service is an abstract concept implemented on platforms by running the same container image (and configuration) one or more times.
- Networks
- Services communicate with each other through Networks. In this specification, a Network is a platform capability abstraction to establish an IP route between containers within services connected together.
- Volumns
- Services store and share persistent data into Volumes. The specification describes such a persistent data as a high-level filesystem mount with global options.
- Configs
- Some services require configuration data that is dependent on the runtime or platform. For this, the specification defines a dedicated concept: Configs.
- Secret
- A Secret is a specific flavor of configuration data for sensitive data that SHOULD NOT be exposed without security considerations. Secrets are made available to services as files mounted into their containers, but the platform-specific resources to provide sensitive data are specific enough to deserve a distinct concept and definition within the Compose specification.
Compose file
- The Compose file is a YAML file defining version (DEPRECATED), services (REQUIRED), networks, volumes, configs and secrets. The default path for a Compose file is
compose.yaml
(preferred) orcompose.yml
in working directory. Compose implementations SHOULD also supportdocker-compose.yaml
anddocker-compose.yml
for backward compatibility. If both files exist, Compose implementations MUST prefer canonical one.compose.yaml