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
Dockerfileand a context. The build’s context is the set of files at a specified locationPATHorURL. ThePATHis a directory on your local filesystem. TheURLis a Git repository location. -
To use a file in the build context, the
Dockerfilerefers to the file specified in an instruction, for example, aCOPYinstruction. To increase the build’s performance, exclude files and directories by adding a.dockerignorefile to the context directory. For information about how to create a.dockerignorefile see the documentation on this page. -
You use the
-fflag withdocker buildto 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 /tmpwill not have any effect on the next instructions. -
Whenever possible, Docker uses a build-cache to accelerate the
docker buildprocess significantly. This is indicated by theCACHEDmessage in the console output. (For more information, see theDockerfilebest 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
Dockerfilein order. ADockerfilemust begin with aFROMinstruction. This may be after parser directives, comments, and globally scoped ARGs. TheFROMinstruction specifies the Parent Image from which you are building.FROMmay only be preceded by one or more instructionsARG, which declare arguments that are used inFROMlines in theDockerfile.
Parser directives
-
Parser directives are optional, and affect the way in which subsequent lines in a
Dockerfileare 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:
syntaxescape
-
-
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/dockerfilerepository on Docker Hub. There are two channels where new images are released:stableandlabs.Stable channel follows semantic versioning. For example:
docker/dockerfile:1- kept updated with the latest1.x.xminor and patch releasedocker/dockerfile:1.2- kept updated with the latest1.2.xpatch release, and stops receiving updates once version1.3.0is 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
-labssuffix, for example:docker/dockerfile:labs- latest release on labs channeldocker/dockerfile:1-labs- same asdockerfile:1in the stable channel, with labs features enableddocker/dockerfile:1.2-labs- same asdockerfile:1.2in the stable channel, with labs features enableddocker/dockerfile:1.2.1-labs- immutable: never updated. Same asdockerfile:1.2.1in the stable channel, with labs features enabled
-
-
escape
# escape=\ (backslash)
Or
# escape=` (backtick)
-
The
escapedirective 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
Dockerfileinstruction to span multiple lines. Note that regardless of whether theescapeparser directive is included in aDockerfile, escaping is not performed in aRUNcommand, 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
ENVstatement) 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 standardbashmodifiers as specified below:${variable:-word}indicates that ifvariableis set then the result will be that value. Ifvariableis not set thenwordwill be the result.${variable:+word}indicates that ifvariableis set thenwordwill be the result, otherwise the result is the empty string.
- Environment variables are supported by the following list of instructions in the
Dockerfile:ADDCOPYENVEXPOSEFROMLABELSTOPSIGNALUSERVOLUMEWORKDIRONBUILD(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
.dockerignorein 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 usingADDorCOPY.
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).
-
FROMcan appear multiple times within a singleDockerfileto 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 newFROMinstruction. EachFROMinstruction clears any state created by previous instructions. -
Optionally a name can be given to a new build stage by adding
AS nameto theFROMinstruction. The name can be used in subsequentFROMandCOPY --from=<name>instructions to refer to the image built in this stage. -
The
tagordigestvalues are optional. If you omit either of them, the builder assumes alatesttag by default. The builder returns an error if it cannot find thetagvalue. -
The optional
--platformflag can be used to specify the platform of the image in caseFROMreferences 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 -con Linux orcmd /S /Con Windows) -
RUN ["executable", "param1", "param2"](exec form)-
The exec form makes it possible to avoid shell string munging, and to
RUNcommands 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
rma file, for example.For systems that have recent aufs version (i.e.,
dirperm1mount option can be set), docker will attempt to fix the issue automatically by mounting the layers withdirperm1option. More details ondirperm1option can be found ataufsman 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
CMDinstruction in aDockerfile. If you list more than oneCMDthen only the lastCMDwill take effect.The main purpose of a
CMDis 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 anENTRYPOINTinstruction as well.If
CMDis used to provide default arguments for theENTRYPOINTinstruction, both theCMDandENTRYPOINTinstructions should be specified with the JSON array format. -
If the user specifies arguments to
docker runthen they will override the default specified inCMD. -
Note:Do not confuse
RUNwithCMD.RUNactually runs a command and commits the result;CMDdoes 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
FROMline) 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 inspectcommand. You can use the--formatoption 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 themacvlandriver 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.noneis 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
--chownfeature 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/passwdand/etc/groupfor translating user and group names to IDs restricts this feature to only be viable for Linux OS-based containers. -
Effect:
- The
ADDinstruction copies new files, directories or remote file URLs from<src>and adds them to the filesystem of the image at the path<dest>. - The
COPYinstruction 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
--chownflag 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/passwdand/etc/groupfiles will be used to perform the translation from name to integer UID or GID respectively.The following examples show valid definitions for the--chownflag: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/passwdor/etc/groupfiles and either user or group names are used in the--chownflag, the build will fail on theADDoperation. 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-Modifiedheader, the timestamp from that header will be used to set themtimeon the destination file. However, like any other file processed during anADD,mtimewill 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 curlor use another tool from within the container as theADDinstruction does not support authentication.
- If the container root filesystem does not contain either
-
Optionally
COPYaccepts 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. -
ADDobeys the following rules:- The
<src>path must be inside the context of the build; you cannotADD ../something /something, because the first step of adocker buildis 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.comwill 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
CMDorENTRYPOINTcommands. ENTRYPOINTshould be defined when using the container as an executable.CMDshould be used as a way of defining default arguments for anENTRYPOINTcommand or for executing an ad-hoc command in a container.CMDwill 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
VOLUMEinstruction does not support specifying ahost-dirparameter. 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_PROXYhttp_proxyHTTPS_PROXYhttps_proxyFTP_PROXYftp_proxyNO_PROXYno_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
ONBUILDinstruction, 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 inspectcommand. - Later the image may be used as a base for a new build, using the
FROMinstruction. As part of processing theFROMinstruction, the downstream builder looks forONBUILDtriggers, and executes them in the same order they were registered. If any of the triggers fail, theFROMinstruction is aborted which in turn causes the build to fail. If all triggers succeed, theFROMinstruction 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
CMDare:-
--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.ymlin working directory. Compose implementations SHOULD also supportdocker-compose.yamlanddocker-compose.ymlfor backward compatibility. If both files exist, Compose implementations MUST prefer canonical one.compose.yaml












