mirror of
https://github.com/genuinetools/reg.git
synced 2024-09-12 06:11:03 -04:00
1960 lines
74 KiB
Markdown
1960 lines
74 KiB
Markdown
![]() |
---
|
|||
|
description: "Dockerfiles use a simple DSL which allows you to automate the steps you would normally manually take to create an image."
|
|||
|
keywords: "builder, docker, Dockerfile, automation, image creation"
|
|||
|
redirect_from:
|
|||
|
- /reference/builder/
|
|||
|
---
|
|||
|
|
|||
|
<!-- This file is maintained within the docker/cli GitHub
|
|||
|
repository at https://github.com/docker/cli/. Make all
|
|||
|
pull requests against that repo. If you see this file in
|
|||
|
another repository, consider it read-only there, as it will
|
|||
|
periodically be overwritten by the definitive file. Pull
|
|||
|
requests which include edits to this file in other repositories
|
|||
|
will be rejected.
|
|||
|
-->
|
|||
|
|
|||
|
# Dockerfile reference
|
|||
|
|
|||
|
Docker can build images automatically by reading the instructions from a
|
|||
|
`Dockerfile`. A `Dockerfile` is a text document that contains all the commands a
|
|||
|
user could call on the command line to assemble an image. Using `docker build`
|
|||
|
users can create an automated build that executes several command-line
|
|||
|
instructions in succession.
|
|||
|
|
|||
|
This page describes the commands you can use in a `Dockerfile`. When you are
|
|||
|
done reading this page, refer to the [`Dockerfile` Best
|
|||
|
Practices](https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/) for a tip-oriented guide.
|
|||
|
|
|||
|
## Usage
|
|||
|
|
|||
|
The [`docker build`](commandline/build.md) command builds an image from
|
|||
|
a `Dockerfile` and a *context*. The build's context is the set of files at a
|
|||
|
specified location `PATH` or `URL`. The `PATH` is a directory on your local
|
|||
|
filesystem. The `URL` is a Git repository location.
|
|||
|
|
|||
|
A context is processed recursively. So, a `PATH` includes any subdirectories and
|
|||
|
the `URL` includes the repository and its submodules. This example shows a
|
|||
|
build command that uses the current directory as context:
|
|||
|
|
|||
|
$ docker build .
|
|||
|
Sending build context to Docker daemon 6.51 MB
|
|||
|
...
|
|||
|
|
|||
|
The build is run by the Docker daemon, not by the CLI. The first thing a build
|
|||
|
process does is send the entire context (recursively) to the daemon. In most
|
|||
|
cases, it's best to start with an empty directory as context and keep your
|
|||
|
Dockerfile in that directory. Add only the files needed for building the
|
|||
|
Dockerfile.
|
|||
|
|
|||
|
>**Warning**: Do not use your root directory, `/`, as the `PATH` as it causes
|
|||
|
>the build to transfer the entire contents of your hard drive to the Docker
|
|||
|
>daemon.
|
|||
|
|
|||
|
To use a file in the build context, the `Dockerfile` refers to the file specified
|
|||
|
in an instruction, for example, a `COPY` 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](#dockerignore-file) see the documentation on this page.
|
|||
|
|
|||
|
Traditionally, the `Dockerfile` is called `Dockerfile` and located in the root
|
|||
|
of the context. You use the `-f` flag with `docker 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 .
|
|||
|
|
|||
|
To tag the image into multiple repositories after the build,
|
|||
|
add multiple `-t` parameters when you run the `build` command:
|
|||
|
|
|||
|
$ docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .
|
|||
|
|
|||
|
Before the Docker daemon runs the instructions in the `Dockerfile`, it performs
|
|||
|
a preliminary validation of the `Dockerfile` and returns an error if the syntax is incorrect:
|
|||
|
|
|||
|
$ docker build -t test/myapp .
|
|||
|
Sending build context to Docker daemon 2.048 kB
|
|||
|
Error response from daemon: Unknown instruction: RUNCMD
|
|||
|
|
|||
|
The Docker daemon runs the instructions in the `Dockerfile` one-by-one,
|
|||
|
committing the result of each instruction
|
|||
|
to a new image if necessary, before finally outputting the ID of your
|
|||
|
new image. The Docker daemon will automatically clean up the context you
|
|||
|
sent.
|
|||
|
|
|||
|
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 will re-use the intermediate images (cache),
|
|||
|
to accelerate the `docker build` process significantly. This is indicated by
|
|||
|
the `Using cache` message in the console output.
|
|||
|
(For more information, see the [Build cache section](https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#build-cache) in the
|
|||
|
`Dockerfile` best practices guide):
|
|||
|
|
|||
|
$ docker build -t svendowideit/ambassador .
|
|||
|
Sending build context to Docker daemon 15.36 kB
|
|||
|
Step 1/4 : FROM alpine:3.2
|
|||
|
---> 31f630c65071
|
|||
|
Step 2/4 : MAINTAINER SvenDowideit@home.org.au
|
|||
|
---> Using cache
|
|||
|
---> 2a1c91448f5f
|
|||
|
Step 3/4 : RUN apk update && apk add socat && rm -r /var/cache/
|
|||
|
---> Using cache
|
|||
|
---> 21ed6e7fbb73
|
|||
|
Step 4/4 : CMD env | grep _TCP= | (sed 's/.*_PORT_\([0-9]*\)_TCP=tcp:\/\/\(.*\):\(.*\)/socat -t 100000000 TCP4-LISTEN:\1,fork,reuseaddr TCP4:\2:\3 \&/' && echo wait) | sh
|
|||
|
---> Using cache
|
|||
|
---> 7ea8aef582cc
|
|||
|
Successfully built 7ea8aef582cc
|
|||
|
|
|||
|
Build cache is only used from images that have a local parent chain. This means
|
|||
|
that these images were created by previous builds or the whole chain of images
|
|||
|
was loaded with `docker load`. If you wish to use build cache of a specific
|
|||
|
image you can specify it with `--cache-from` option. Images specified with
|
|||
|
`--cache-from` do not need to have a parent chain and may be pulled from other
|
|||
|
registries.
|
|||
|
|
|||
|
When you're done with your build, you're ready to look into [*Pushing a
|
|||
|
repository to its registry*](https://docs.docker.com/engine/tutorials/dockerrepos/#/contributing-to-docker-hub).
|
|||
|
|
|||
|
## Format
|
|||
|
|
|||
|
Here is the format of the `Dockerfile`:
|
|||
|
|
|||
|
```Dockerfile
|
|||
|
# Comment
|
|||
|
INSTRUCTION arguments
|
|||
|
```
|
|||
|
|
|||
|
The instruction is not case-sensitive. However, convention is for them to
|
|||
|
be UPPERCASE to distinguish them from arguments more easily.
|
|||
|
|
|||
|
|
|||
|
Docker runs instructions in a `Dockerfile` in order. A `Dockerfile` **must
|
|||
|
start with a \`FROM\` instruction**. The `FROM` instruction specifies the [*Base
|
|||
|
Image*](glossary.md#base-image) from which you are building. `FROM` may only be
|
|||
|
preceded by one or more `ARG` instructions, which declare arguments that are used
|
|||
|
in `FROM` lines in the `Dockerfile`.
|
|||
|
|
|||
|
Docker treats lines that *begin* with `#` as a comment, unless the line is
|
|||
|
a valid [parser directive](#parser-directives). A `#` marker anywhere
|
|||
|
else in a line is treated as an argument. This allows statements like:
|
|||
|
|
|||
|
```Dockerfile
|
|||
|
# Comment
|
|||
|
RUN echo 'we are running some # of cool things'
|
|||
|
```
|
|||
|
|
|||
|
Line continuation characters are not supported in comments.
|
|||
|
|
|||
|
## 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.
|
|||
|
|
|||
|
Due to these rules, the following examples are all invalid:
|
|||
|
|
|||
|
Invalid due to line continuation:
|
|||
|
|
|||
|
```Dockerfile
|
|||
|
# direc \
|
|||
|
tive=value
|
|||
|
```
|
|||
|
|
|||
|
Invalid due to appearing twice:
|
|||
|
|
|||
|
```Dockerfile
|
|||
|
# directive=value1
|
|||
|
# directive=value2
|
|||
|
|
|||
|
FROM ImageName
|
|||
|
```
|
|||
|
|
|||
|
Treated as a comment due to appearing after a builder instruction:
|
|||
|
|
|||
|
```Dockerfile
|
|||
|
FROM ImageName
|
|||
|
# directive=value
|
|||
|
```
|
|||
|
|
|||
|
Treated as a comment due to appearing after a comment which is not a parser
|
|||
|
directive:
|
|||
|
|
|||
|
```Dockerfile
|
|||
|
# 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.
|
|||
|
|
|||
|
```Dockerfile
|
|||
|
# unknowndirective=value
|
|||
|
# knowndirective=value
|
|||
|
```
|
|||
|
|
|||
|
Non line-breaking whitespace is permitted in a parser directive. Hence, the
|
|||
|
following lines are all treated identically:
|
|||
|
|
|||
|
```Dockerfile
|
|||
|
#directive=value
|
|||
|
# directive =value
|
|||
|
# directive= value
|
|||
|
# directive = value
|
|||
|
# dIrEcTiVe=value
|
|||
|
```
|
|||
|
|
|||
|
The following parser directive is supported:
|
|||
|
|
|||
|
* `escape`
|
|||
|
|
|||
|
## escape
|
|||
|
|
|||
|
# escape=\ (backslash)
|
|||
|
|
|||
|
Or
|
|||
|
|
|||
|
# escape=` (backtick)
|
|||
|
|
|||
|
The `escape` directive sets the character used to escape characters in a
|
|||
|
`Dockerfile`. 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 the `escape` parser
|
|||
|
directive is included in a `Dockerfile`, *escaping is not performed in
|
|||
|
a `RUN` 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](https://technet.microsoft.com/en-us/library/hh847755.aspx).
|
|||
|
|
|||
|
Consider the following example which would fail in a non-obvious way on
|
|||
|
`Windows`. The second `\` at the end of the second line would be interpreted as an
|
|||
|
escape for the newline, instead of a target of the escape from the first `\`.
|
|||
|
Similarly, the `\` at the end of the third line would, assuming it was actually
|
|||
|
handled as an instruction, cause it be treated as a line continuation. The result
|
|||
|
of this dockerfile is that second and third lines are considered a single
|
|||
|
instruction:
|
|||
|
|
|||
|
```Dockerfile
|
|||
|
FROM microsoft/nanoserver
|
|||
|
COPY testfile.txt c:\\
|
|||
|
RUN dir c:\
|
|||
|
```
|
|||
|
|
|||
|
Results in:
|
|||
|
|
|||
|
PS C:\John> docker build -t cmd .
|
|||
|
Sending build context to Docker daemon 3.072 kB
|
|||
|
Step 1/2 : FROM microsoft/nanoserver
|
|||
|
---> 22738ff49c6d
|
|||
|
Step 2/2 : COPY testfile.txt c:\RUN dir c:
|
|||
|
GetFileAttributesEx c:RUN: The system cannot find the file specified.
|
|||
|
PS C:\John>
|
|||
|
|
|||
|
One solution to the above would be to use `/` as the target of both the `COPY`
|
|||
|
instruction, and `dir`. However, this syntax is, at best, confusing as it is not
|
|||
|
natural for paths on `Windows`, and at worst, error prone as not all commands on
|
|||
|
`Windows` support `/` as the path separator.
|
|||
|
|
|||
|
By adding the `escape` parser directive, the following `Dockerfile` succeeds as
|
|||
|
expected with the use of natural platform semantics for file paths on `Windows`:
|
|||
|
|
|||
|
# escape=`
|
|||
|
|
|||
|
FROM microsoft/nanoserver
|
|||
|
COPY testfile.txt c:\
|
|||
|
RUN dir c:\
|
|||
|
|
|||
|
Results in:
|
|||
|
|
|||
|
PS C:\John> docker build -t succeeds --no-cache=true .
|
|||
|
Sending build context to Docker daemon 3.072 kB
|
|||
|
Step 1/3 : FROM microsoft/nanoserver
|
|||
|
---> 22738ff49c6d
|
|||
|
Step 2/3 : COPY testfile.txt c:\
|
|||
|
---> 96655de338de
|
|||
|
Removing intermediate container 4db9acbb1682
|
|||
|
Step 3/3 : RUN dir c:\
|
|||
|
---> Running in a2c157f842f5
|
|||
|
Volume in drive C has no label.
|
|||
|
Volume Serial Number is 7E6D-E0F7
|
|||
|
|
|||
|
Directory of c:\
|
|||
|
|
|||
|
10/05/2016 05:04 PM 1,894 License.txt
|
|||
|
10/05/2016 02:22 PM <DIR> Program Files
|
|||
|
10/05/2016 02:14 PM <DIR> Program Files (x86)
|
|||
|
10/28/2016 11:18 AM 62 testfile.txt
|
|||
|
10/28/2016 11:20 AM <DIR> Users
|
|||
|
10/28/2016 11:20 AM <DIR> Windows
|
|||
|
2 File(s) 1,956 bytes
|
|||
|
4 Dir(s) 21,259,096,064 bytes free
|
|||
|
---> 01c7f3bef04f
|
|||
|
Removing intermediate container a2c157f842f5
|
|||
|
Successfully built 01c7f3bef04f
|
|||
|
PS C:\John>
|
|||
|
|
|||
|
## Environment replacement
|
|||
|
|
|||
|
Environment variables (declared with [the `ENV` statement](#env)) can also be
|
|||
|
used in certain instructions as variables to be interpreted by the
|
|||
|
`Dockerfile`. Escapes are also handled for including variable-like syntax
|
|||
|
into a statement literally.
|
|||
|
|
|||
|
Environment variables are notated in the `Dockerfile` either with
|
|||
|
`$variable_name` or `${variable_name}`. They are treated equivalently and the
|
|||
|
brace syntax is typically used to address issues with variable names with no
|
|||
|
whitespace, like `${foo}_bar`.
|
|||
|
|
|||
|
The `${variable_name}` syntax also supports a few of the standard `bash`
|
|||
|
modifiers as specified below:
|
|||
|
|
|||
|
* `${variable:-word}` indicates that if `variable` is set then the result
|
|||
|
will be that value. If `variable` is not set then `word` will be the result.
|
|||
|
* `${variable:+word}` indicates that if `variable` is set then `word` will be
|
|||
|
the result, otherwise the result is the empty string.
|
|||
|
|
|||
|
In all cases, `word` can be any string, including additional environment
|
|||
|
variables.
|
|||
|
|
|||
|
Escaping is possible by adding a `\` before the variable: `\$foo` or `\${foo}`,
|
|||
|
for example, will translate to `$foo` and `${foo}` literals respectively.
|
|||
|
|
|||
|
Example (parsed representation is displayed after the `#`):
|
|||
|
|
|||
|
FROM busybox
|
|||
|
ENV foo /bar
|
|||
|
WORKDIR ${foo} # WORKDIR /bar
|
|||
|
ADD . $foo # ADD . /bar
|
|||
|
COPY \$foo /quux # COPY $foo /quux
|
|||
|
|
|||
|
Environment variables are supported by the following list of instructions in
|
|||
|
the `Dockerfile`:
|
|||
|
|
|||
|
* `ADD`
|
|||
|
* `COPY`
|
|||
|
* `ENV`
|
|||
|
* `EXPOSE`
|
|||
|
* `FROM`
|
|||
|
* `LABEL`
|
|||
|
* `STOPSIGNAL`
|
|||
|
* `USER`
|
|||
|
* `VOLUME`
|
|||
|
* `WORKDIR`
|
|||
|
|
|||
|
as well as:
|
|||
|
|
|||
|
* `ONBUILD` (when combined with one of the supported instructions above)
|
|||
|
|
|||
|
> **Note**:
|
|||
|
> prior to 1.4, `ONBUILD` instructions did **NOT** support environment
|
|||
|
> variable, even when combined with any of the instructions listed above.
|
|||
|
|
|||
|
Environment variable substitution will use the same value for each variable
|
|||
|
throughout the entire instruction. In other words, in this example:
|
|||
|
|
|||
|
ENV abc=hello
|
|||
|
ENV abc=bye def=$abc
|
|||
|
ENV ghi=$abc
|
|||
|
|
|||
|
will result in `def` having a value of `hello`, not `bye`. However,
|
|||
|
`ghi` will have a value of `bye` because it is not part of the same instruction
|
|||
|
that set `abc` to `bye`.
|
|||
|
|
|||
|
## .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 using `ADD` or `COPY`.
|
|||
|
|
|||
|
The CLI interprets the `.dockerignore` file as a newline-separated
|
|||
|
list of patterns similar to the file globs of Unix shells. For the
|
|||
|
purposes of matching, the root of the context is considered to be both
|
|||
|
the working and the root directory. For example, the patterns
|
|||
|
`/foo/bar` and `foo/bar` both exclude a file or directory named `bar`
|
|||
|
in the `foo` subdirectory of `PATH` or in the root of the git
|
|||
|
repository located at `URL`. Neither excludes anything else.
|
|||
|
|
|||
|
If a line in `.dockerignore` file starts with `#` in column 1, then this line is
|
|||
|
considered as a comment and is ignored before interpreted by the CLI.
|
|||
|
|
|||
|
Here is an example `.dockerignore` file:
|
|||
|
|
|||
|
```
|
|||
|
# comment
|
|||
|
*/temp*
|
|||
|
*/*/temp*
|
|||
|
temp?
|
|||
|
```
|
|||
|
|
|||
|
This file causes the following build behavior:
|
|||
|
|
|||
|
| Rule | Behavior |
|
|||
|
|:------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|||
|
| `# comment` | Ignored. |
|
|||
|
| `*/temp*` | Exclude files and directories whose names start with `temp` in any immediate subdirectory of the root. For example, the plain file `/somedir/temporary.txt` is excluded, as is the directory `/somedir/temp`. |
|
|||
|
| `*/*/temp*` | Exclude files and directories starting with `temp` from any subdirectory that is two levels below the root. For example, `/somedir/subdir/temporary.txt` is excluded. |
|
|||
|
| `temp?` | Exclude files and directories in the root directory whose names are a one-character extension of `temp`. For example, `/tempa` and `/tempb` are excluded. |
|
|||
|
|
|||
|
|
|||
|
Matching is done using Go's
|
|||
|
[filepath.Match](http://golang.org/pkg/path/filepath#Match) rules. A
|
|||
|
preprocessing step removes leading and trailing whitespace and
|
|||
|
eliminates `.` and `..` elements using Go's
|
|||
|
[filepath.Clean](http://golang.org/pkg/path/filepath/#Clean). Lines
|
|||
|
that are blank after preprocessing are ignored.
|
|||
|
|
|||
|
Beyond Go's filepath.Match rules, Docker also supports a special
|
|||
|
wildcard string `**` that matches any number of directories (including
|
|||
|
zero). For example, `**/*.go` will exclude all files that end with `.go`
|
|||
|
that are found in all directories, including the root of the build context.
|
|||
|
|
|||
|
Lines starting with `!` (exclamation mark) can be used to make exceptions
|
|||
|
to exclusions. The following is an example `.dockerignore` file that
|
|||
|
uses this mechanism:
|
|||
|
|
|||
|
```
|
|||
|
*.md
|
|||
|
!README.md
|
|||
|
```
|
|||
|
|
|||
|
All markdown files *except* `README.md` are excluded from the context.
|
|||
|
|
|||
|
The placement of `!` exception rules influences the behavior: the last
|
|||
|
line of the `.dockerignore` that matches a particular file determines
|
|||
|
whether it is included or excluded. Consider the following example:
|
|||
|
|
|||
|
```
|
|||
|
*.md
|
|||
|
!README*.md
|
|||
|
README-secret.md
|
|||
|
```
|
|||
|
|
|||
|
No markdown files are included in the context except README files other than
|
|||
|
`README-secret.md`.
|
|||
|
|
|||
|
Now consider this example:
|
|||
|
|
|||
|
```
|
|||
|
*.md
|
|||
|
README-secret.md
|
|||
|
!README*.md
|
|||
|
```
|
|||
|
|
|||
|
All of the README files are included. The middle line has no effect because
|
|||
|
`!README*.md` matches `README-secret.md` and comes last.
|
|||
|
|
|||
|
You can even use the `.dockerignore` file to exclude the `Dockerfile`
|
|||
|
and `.dockerignore` files. These files are still sent to the daemon
|
|||
|
because it needs them to do its job. But the `ADD` and `COPY` instructions
|
|||
|
do not copy them to the image.
|
|||
|
|
|||
|
Finally, you may want to specify which files to include in the
|
|||
|
context, rather than which to exclude. To achieve this, specify `*` as
|
|||
|
the first pattern, followed by one or more `!` exception patterns.
|
|||
|
|
|||
|
**Note**: For historical reasons, the pattern `.` is ignored.
|
|||
|
|
|||
|
## FROM
|
|||
|
|
|||
|
FROM <image> [AS <name>]
|
|||
|
|
|||
|
Or
|
|||
|
|
|||
|
FROM <image>[:<tag>] [AS <name>]
|
|||
|
|
|||
|
Or
|
|||
|
|
|||
|
FROM <image>[@<digest>] [AS <name>]
|
|||
|
|
|||
|
The `FROM` instruction initializes a new build stage and sets the
|
|||
|
[*Base Image*](glossary.md#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*](https://docs.docker.com/engine/tutorials/dockerrepos/).
|
|||
|
|
|||
|
- `ARG` is the only instruction that may precede `FROM` in the `Dockerfile`.
|
|||
|
See [Understand how ARG and FROM interact](#understand-how-arg-and-from-interact).
|
|||
|
|
|||
|
- `FROM` can appear multiple times within a single `Dockerfile` 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 new
|
|||
|
`FROM` instruction. Each `FROM` instruction clears any state created by previous
|
|||
|
instructions.
|
|||
|
|
|||
|
- Optionally a name can be given to a new build stage by adding `AS name` to the
|
|||
|
`FROM` instruction. The name can be used in subsequent `FROM` and
|
|||
|
`COPY --from=<name|index>` instructions to refer to the image built in this stage.
|
|||
|
|
|||
|
- The `tag` or `digest` values are optional. If you omit either of them, the
|
|||
|
builder assumes a `latest` tag by default. The builder returns an error if it
|
|||
|
cannot find the `tag` value.
|
|||
|
|
|||
|
### Understand how ARG and FROM interact
|
|||
|
|
|||
|
`FROM` instructions support variables that are declared by any `ARG`
|
|||
|
instructions that occur before the first `FROM`.
|
|||
|
|
|||
|
```Dockerfile
|
|||
|
ARG CODE_VERSION=latest
|
|||
|
FROM base:${CODE_VERSION}
|
|||
|
CMD /code/run-app
|
|||
|
|
|||
|
FROM extras:${CODE_VERSION}
|
|||
|
CMD /code/run-extras
|
|||
|
```
|
|||
|
|
|||
|
An `ARG` declared before a `FROM` is outside of a build stage, so it
|
|||
|
can't be used in any instruction after a `FROM`. To use the default value of
|
|||
|
an `ARG` declared before the first `FROM` use an `ARG` instruction without
|
|||
|
a value inside of a build stage:
|
|||
|
|
|||
|
```Dockerfile
|
|||
|
ARG VERSION=latest
|
|||
|
FROM busybox:$VERSION
|
|||
|
ARG VERSION
|
|||
|
RUN echo $VERSION > image_version
|
|||
|
```
|
|||
|
|
|||
|
## 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 or `cmd /S /C` on Windows)
|
|||
|
- `RUN ["executable", "param1", "param2"]` (*exec* form)
|
|||
|
|
|||
|
The `RUN` instruction will execute any commands in a new layer on top of the
|
|||
|
current image and commit the results. The resulting committed image will be
|
|||
|
used for the next step in the `Dockerfile`.
|
|||
|
|
|||
|
Layering `RUN` instructions and generating commits conforms to the core
|
|||
|
concepts of Docker where commits are cheap and containers can be created from
|
|||
|
any point in an image's history, much like source control.
|
|||
|
|
|||
|
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.
|
|||
|
|
|||
|
The default shell for the *shell* form can be changed using the `SHELL`
|
|||
|
command.
|
|||
|
|
|||
|
In the *shell* form you can use a `\` (backslash) to continue a single
|
|||
|
RUN instruction onto the next line. For example, consider these two lines:
|
|||
|
|
|||
|
```
|
|||
|
RUN /bin/bash -c 'source $HOME/.bashrc; \
|
|||
|
echo $HOME'
|
|||
|
```
|
|||
|
Together they are equivalent to this single line:
|
|||
|
|
|||
|
```
|
|||
|
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'
|
|||
|
```
|
|||
|
|
|||
|
> **Note**:
|
|||
|
> 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 (').
|
|||
|
|
|||
|
> **Note**:
|
|||
|
> Unlike the *shell* form, the *exec* form does not invoke a command shell.
|
|||
|
> This means that normal shell processing does not happen. For example,
|
|||
|
> `RUN [ "echo", "$HOME" ]` will not do variable substitution on `$HOME`.
|
|||
|
> If you want shell processing then either use the *shell* form or execute
|
|||
|
> a shell directly, for example: `RUN [ "sh", "-c", "echo $HOME" ]`.
|
|||
|
> When using the exec form and executing a shell directly, as in the case for
|
|||
|
> the shell form, it is the shell that is doing the environment variable
|
|||
|
> expansion, not docker.
|
|||
|
>
|
|||
|
> **Note**:
|
|||
|
> In the *JSON* form, it is necessary to escape backslashes. This is
|
|||
|
> particularly relevant on Windows where the backslash is the path separator.
|
|||
|
> The following line would otherwise be treated as *shell* form due to not
|
|||
|
> being valid JSON, and fail in an unexpected way:
|
|||
|
> `RUN ["c:\windows\system32\tasklist.exe"]`
|
|||
|
> The correct syntax for this example is:
|
|||
|
> `RUN ["c:\\windows\\system32\\tasklist.exe"]`
|
|||
|
|
|||
|
The cache for `RUN` instructions isn't invalidated automatically during
|
|||
|
the next build. The cache for an instruction like
|
|||
|
`RUN apt-get dist-upgrade -y` will be reused during the next build. The
|
|||
|
cache for `RUN` instructions can be invalidated by using the `--no-cache`
|
|||
|
flag, for example `docker build --no-cache`.
|
|||
|
|
|||
|
See the [`Dockerfile` Best Practices
|
|||
|
guide](https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#/build-cache) for more information.
|
|||
|
|
|||
|
The cache for `RUN` instructions can be invalidated by `ADD` instructions. See
|
|||
|
[below](#add) for details.
|
|||
|
|
|||
|
### Known issues (RUN)
|
|||
|
|
|||
|
- [Issue 783](https://github.com/docker/docker/issues/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 with `dirperm1` option. More details on `dirperm1` option can be
|
|||
|
found at [`aufs` man page](https://github.com/sfjro/aufs3-linux/tree/aufs3.18/Documentation/filesystems/aufs)
|
|||
|
|
|||
|
If 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 a `Dockerfile`. If you list more than one `CMD`
|
|||
|
then only the last `CMD` 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 an `ENTRYPOINT`
|
|||
|
instruction as well.
|
|||
|
|
|||
|
> **Note**:
|
|||
|
> If `CMD` is used to provide default arguments for the `ENTRYPOINT`
|
|||
|
> instruction, both the `CMD` and `ENTRYPOINT` instructions should be specified
|
|||
|
> with the JSON array format.
|
|||
|
|
|||
|
> **Note**:
|
|||
|
> The *exec* form is parsed as a JSON array, which means that
|
|||
|
> you must use double-quotes (") around words not single-quotes (').
|
|||
|
|
|||
|
> **Note**:
|
|||
|
> Unlike the *shell* form, the *exec* form does not invoke a command shell.
|
|||
|
> This means that normal shell processing does not happen. For example,
|
|||
|
> `CMD [ "echo", "$HOME" ]` will not do variable substitution on `$HOME`.
|
|||
|
> If you want shell processing then either use the *shell* form or execute
|
|||
|
> a shell directly, for example: `CMD [ "sh", "-c", "echo $HOME" ]`.
|
|||
|
> When using the exec form and executing a shell directly, as in the case for
|
|||
|
> the shell form, it is the shell that is doing the environment variable
|
|||
|
> expansion, not docker.
|
|||
|
|
|||
|
When used in the shell or exec formats, the `CMD` instruction sets the command
|
|||
|
to be executed when running the image.
|
|||
|
|
|||
|
If you use the *shell* form of the `CMD`, then the `<command>` will execute in
|
|||
|
`/bin/sh -c`:
|
|||
|
|
|||
|
FROM ubuntu
|
|||
|
CMD echo "This is a test." | wc -
|
|||
|
|
|||
|
If you want to **run your** `<command>` **without a shell** then you must
|
|||
|
express the command as a JSON array and give the full path to the executable.
|
|||
|
**This array form is the preferred format of `CMD`.** Any additional parameters
|
|||
|
must be individually expressed as strings in the array:
|
|||
|
|
|||
|
FROM ubuntu
|
|||
|
CMD ["/usr/bin/wc","--help"]
|
|||
|
|
|||
|
If you would like your container to run the same executable every time, then
|
|||
|
you should consider using `ENTRYPOINT` in combination with `CMD`. See
|
|||
|
[*ENTRYPOINT*](#entrypoint).
|
|||
|
|
|||
|
If the user specifies arguments to `docker run` then they will override the
|
|||
|
default specified in `CMD`.
|
|||
|
|
|||
|
> **Note**:
|
|||
|
> Don't confuse `RUN` with `CMD`. `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"
|
|||
|
LABEL com.example.label-with-value="foo"
|
|||
|
LABEL version="1.0"
|
|||
|
LABEL description="This text illustrates \
|
|||
|
that label-values can span multiple lines."
|
|||
|
|
|||
|
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:
|
|||
|
|
|||
|
```none
|
|||
|
LABEL multi.label1="value1" multi.label2="value2" other="value3"
|
|||
|
```
|
|||
|
|
|||
|
```none
|
|||
|
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 inspect` command.
|
|||
|
|
|||
|
"Labels": {
|
|||
|
"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)
|
|||
|
|
|||
|
MAINTAINER <name>
|
|||
|
|
|||
|
The `MAINTAINER` instruction sets the *Author* field of the generated images.
|
|||
|
The `LABEL` instruction is a much more flexible version of this and you should use
|
|||
|
it instead, as it enables setting any metadata you require, and can be viewed
|
|||
|
easily, for example with `docker inspect`. To set a label corresponding to the
|
|||
|
`MAINTAINER` field you could use:
|
|||
|
|
|||
|
LABEL maintainer="SvenDowideit@home.org.au"
|
|||
|
|
|||
|
This will then be visible from `docker inspect` with the other labels.
|
|||
|
|
|||
|
## 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.
|
|||
|
|
|||
|
To set up port redirection on the host system, see [using the -P
|
|||
|
flag](run.md#expose-incoming-ports). 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](https://docs.docker.com/engine/userguide/networking/)).
|
|||
|
|
|||
|
## ENV
|
|||
|
|
|||
|
ENV <key> <value>
|
|||
|
ENV <key>=<value> ...
|
|||
|
|
|||
|
The `ENV` instruction sets the environment variable `<key>` to the value
|
|||
|
`<value>`. This value will be in the environment of all "descendant"
|
|||
|
`Dockerfile` commands and can be [replaced inline](#environment-replacement) in
|
|||
|
many as well.
|
|||
|
|
|||
|
The `ENV` instruction has two forms. The first form, `ENV <key> <value>`,
|
|||
|
will set a single variable to a value. The entire string after the first
|
|||
|
space will be treated as the `<value>` - including characters such as
|
|||
|
spaces and quotes.
|
|||
|
|
|||
|
The second form, `ENV <key>=<value> ...`, allows for multiple variables to
|
|||
|
be set at one time. Notice that the second form uses the equals sign (=)
|
|||
|
in the syntax, while the first form does not. Like command line parsing,
|
|||
|
quotes and backslashes can be used to include spaces within values.
|
|||
|
|
|||
|
For example:
|
|||
|
|
|||
|
ENV myName="John Doe" myDog=Rex\ The\ Dog \
|
|||
|
myCat=fluffy
|
|||
|
|
|||
|
and
|
|||
|
|
|||
|
ENV myName John Doe
|
|||
|
ENV myDog Rex The Dog
|
|||
|
ENV myCat fluffy
|
|||
|
|
|||
|
will yield the same net results in the final image, but the first form
|
|||
|
is preferred because it produces a single cache layer.
|
|||
|
|
|||
|
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>`.
|
|||
|
|
|||
|
> **Note**:
|
|||
|
> Environment persistence can cause unexpected side effects. For example,
|
|||
|
> setting `ENV DEBIAN_FRONTEND noninteractive` may confuse apt-get
|
|||
|
> users on a Debian-based image. To set a value for a single command, use
|
|||
|
> `RUN <key>=<value> <command>`.
|
|||
|
|
|||
|
## ADD
|
|||
|
|
|||
|
ADD has two forms:
|
|||
|
|
|||
|
- `ADD [--chown=<user>:<group>] <src>... <dest>`
|
|||
|
- `ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]` (this form is required for paths containing
|
|||
|
whitespace)
|
|||
|
|
|||
|
> **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
|
|||
|
> for Linux OS-based containers.
|
|||
|
|
|||
|
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>`.
|
|||
|
|
|||
|
Multiple `<src>` resources may be specified but if they are files or
|
|||
|
directories, their paths are interpreted as relative to the source of
|
|||
|
the context of the build.
|
|||
|
|
|||
|
Each `<src>` may contain wildcards and matching will be done using Go's
|
|||
|
[filepath.Match](http://golang.org/pkg/path/filepath#Match) rules. For example:
|
|||
|
|
|||
|
ADD hom* /mydir/ # adds all files starting with "hom"
|
|||
|
ADD hom?.txt /mydir/ # ? is replaced with any single character, e.g., "home.txt"
|
|||
|
|
|||
|
The `<dest>` is an absolute path, or a path relative to `WORKDIR`, into which
|
|||
|
the source will be copied inside the destination container.
|
|||
|
|
|||
|
ADD test relativeDir/ # adds "test" to `WORKDIR`/relativeDir/
|
|||
|
ADD test /absoluteDir/ # adds "test" to /absoluteDir/
|
|||
|
|
|||
|
When adding files or directories that contain special characters (such as `[`
|
|||
|
and `]`), you need to escape those paths following the Golang rules to prevent
|
|||
|
them from being treated as a matching pattern. For example, to add a file
|
|||
|
named `arr[0].txt`, use the following;
|
|||
|
|
|||
|
ADD arr[[]0].txt /mydir/ # copy a file named "arr[0].txt" to /mydir/
|
|||
|
|
|||
|
|
|||
|
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. The
|
|||
|
format of the `--chown` flag allows for either username and groupname strings
|
|||
|
or direct integer UID and GID in any combination. Providing a username without
|
|||
|
groupname or a UID without GID will use the same numeric UID as the GID. 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/
|
|||
|
|
|||
|
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 the `ADD` 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 HTTP
|
|||
|
`Last-Modified` header, the timestamp from that header will be used
|
|||
|
to set the `mtime` on the destination file. However, like any other file
|
|||
|
processed during an `ADD`, `mtime` will not be included in the determination
|
|||
|
of whether or not the file has changed and the cache should be updated.
|
|||
|
|
|||
|
> **Note**:
|
|||
|
> If you build by passing a `Dockerfile` through STDIN (`docker
|
|||
|
> build - < somefile`), there is no build context, so the `Dockerfile`
|
|||
|
> can only contain a URL based `ADD` instruction. You can also pass a
|
|||
|
> compressed archive through STDIN: (`docker build - < archive.tar.gz`),
|
|||
|
> the `Dockerfile` at the root of the archive and the rest of the
|
|||
|
> archive will be used as the context of the build.
|
|||
|
|
|||
|
> **Note**:
|
|||
|
> If your URL files are protected using authentication, you
|
|||
|
> will need to use `RUN wget`, `RUN curl` or use another tool from
|
|||
|
> within the container as the `ADD` instruction does not support
|
|||
|
> authentication.
|
|||
|
|
|||
|
> **Note**:
|
|||
|
> The first encountered `ADD` instruction will invalidate the cache for all
|
|||
|
> following instructions from the Dockerfile if the contents of `<src>` have
|
|||
|
> changed. This includes invalidating the cache for `RUN` instructions.
|
|||
|
> See the [`Dockerfile` Best Practices
|
|||
|
guide](https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#/build-cache) for more information.
|
|||
|
|
|||
|
|
|||
|
`ADD` obeys the following rules:
|
|||
|
|
|||
|
- The `<src>` path must be inside the *context* of the build;
|
|||
|
you cannot `ADD ../something /something`, because the first step of a
|
|||
|
`docker 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.
|
|||
|
|
|||
|
> **Note**:
|
|||
|
> The directory itself is not copied, just its contents.
|
|||
|
|
|||
|
- 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. When a directory is copied or
|
|||
|
unpacked, it has the same behavior as `tar -x`, the result is the union of:
|
|||
|
|
|||
|
1. Whatever existed at the destination path and
|
|||
|
2. The contents of the source tree, with conflicts resolved in favor
|
|||
|
of "2." on a file-by-file basis.
|
|||
|
|
|||
|
> **Note**:
|
|||
|
> Whether a file is identified as a recognized compression format or not
|
|||
|
> is done solely based on the contents of the file, not the name of the file.
|
|||
|
> For example, if an empty file happens to end with `.tar.gz` this will not
|
|||
|
> be recognized as a compressed file and **will not** generate any kind of
|
|||
|
> decompression error message, rather the file will simply be copied to the
|
|||
|
> destination.
|
|||
|
|
|||
|
- If `<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.
|
|||
|
|
|||
|
## COPY
|
|||
|
|
|||
|
COPY has two forms:
|
|||
|
|
|||
|
- `COPY [--chown=<user>:<group>] <src>... <dest>`
|
|||
|
- `COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]` (this form is required for paths containing
|
|||
|
whitespace)
|
|||
|
|
|||
|
> **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
|
|||
|
> for Linux OS-based containers.
|
|||
|
|
|||
|
The `COPY` instruction copies new files or directories from `<src>`
|
|||
|
and adds them to the filesystem of the container at the path `<dest>`.
|
|||
|
|
|||
|
Multiple `<src>` resources may be specified but the paths of files and
|
|||
|
directories will be interpreted as relative to the source of the context
|
|||
|
of the build.
|
|||
|
|
|||
|
Each `<src>` may contain wildcards and matching will be done using Go's
|
|||
|
[filepath.Match](http://golang.org/pkg/path/filepath#Match) rules. For example:
|
|||
|
|
|||
|
COPY hom* /mydir/ # adds all files starting with "hom"
|
|||
|
COPY hom?.txt /mydir/ # ? is replaced with any single character, e.g., "home.txt"
|
|||
|
|
|||
|
The `<dest>` is an absolute path, or a path relative to `WORKDIR`, into which
|
|||
|
the source will be copied inside the destination container.
|
|||
|
|
|||
|
COPY test relativeDir/ # adds "test" to `WORKDIR`/relativeDir/
|
|||
|
COPY test /absoluteDir/ # adds "test" to /absoluteDir/
|
|||
|
|
|||
|
|
|||
|
When copying files or directories that contain special characters (such as `[`
|
|||
|
and `]`), you need to escape those paths following the Golang rules to prevent
|
|||
|
them from being treated as a matching pattern. For example, to copy a file
|
|||
|
named `arr[0].txt`, use the following;
|
|||
|
|
|||
|
COPY arr[[]0].txt /mydir/ # copy a file named "arr[0].txt" to /mydir/
|
|||
|
|
|||
|
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 copied content. The
|
|||
|
format of the `--chown` flag allows for either username and groupname strings
|
|||
|
or direct integer UID and GID in any combination. Providing a username without
|
|||
|
groupname or a UID without GID will use the same numeric UID as the GID. 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:
|
|||
|
|
|||
|
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 the `COPY` operation. Using numeric IDs requires
|
|||
|
no lookup and will not depend on container root filesystem content.
|
|||
|
|
|||
|
> **Note**:
|
|||
|
> If you build using STDIN (`docker build - < somefile`), there is no
|
|||
|
> build context, so `COPY` can't be used.
|
|||
|
|
|||
|
Optionally `COPY` accepts a flag `--from=<name|index>` that can be used to set
|
|||
|
the source location to a previous build stage (created with `FROM .. AS <name>`)
|
|||
|
that will be used instead of a build context sent by the user. The flag also
|
|||
|
accepts a numeric index assigned for all previous build stages started with
|
|||
|
`FROM` instruction. 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.
|
|||
|
|
|||
|
`COPY` obeys the following rules:
|
|||
|
|
|||
|
- The `<src>` path must be inside the *context* of the build;
|
|||
|
you cannot `COPY ../something /something`, because the first step of a
|
|||
|
`docker build` is to send the context directory (and subdirectories) to the
|
|||
|
docker daemon.
|
|||
|
|
|||
|
- If `<src>` is a directory, the entire contents of the directory are copied,
|
|||
|
including filesystem metadata.
|
|||
|
|
|||
|
> **Note**:
|
|||
|
> The directory itself is not copied, just its contents.
|
|||
|
|
|||
|
- If `<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.
|
|||
|
|
|||
|
## ENTRYPOINT
|
|||
|
|
|||
|
ENTRYPOINT has two forms:
|
|||
|
|
|||
|
- `ENTRYPOINT ["executable", "param1", "param2"]`
|
|||
|
(*exec* form, preferred)
|
|||
|
- `ENTRYPOINT command param1 param2`
|
|||
|
(*shell* form)
|
|||
|
|
|||
|
An `ENTRYPOINT` allows you to configure a container that will run as an executable.
|
|||
|
|
|||
|
For example, the following will start nginx with its default content, listening
|
|||
|
on port 80:
|
|||
|
|
|||
|
docker run -i -t --rm -p 80:80 nginx
|
|||
|
|
|||
|
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
|
|||
|
ENTRYPOINT ["top", "-b"]
|
|||
|
CMD ["-c"]
|
|||
|
|
|||
|
When you run the container, you can see that `top` is the only process:
|
|||
|
|
|||
|
$ docker run -it --rm --name test top -H
|
|||
|
top - 08:25:00 up 7:27, 0 users, load average: 0.00, 0.01, 0.05
|
|||
|
Threads: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie
|
|||
|
%Cpu(s): 0.1 us, 0.1 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
|
|||
|
KiB Mem: 2056668 total, 1616832 used, 439836 free, 99352 buffers
|
|||
|
KiB Swap: 1441840 total, 0 used, 1441840 free. 1324440 cached Mem
|
|||
|
|
|||
|
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
|
|||
|
1 root 20 0 19744 2336 2080 R 0.0 0.1 0:00.04 top
|
|||
|
|
|||
|
To examine the result further, you can use `docker exec`:
|
|||
|
|
|||
|
$ docker exec -it test ps aux
|
|||
|
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
|
|||
|
root 1 2.6 0.1 19752 2352 ? Ss+ 08:24 0:00 top -b -H
|
|||
|
root 7 0.0 0.1 15572 2164 ? R+ 08:25 0:00 ps aux
|
|||
|
|
|||
|
And you can gracefully request `top` to shut down using `docker stop test`.
|
|||
|
|
|||
|
The following `Dockerfile` shows using the `ENTRYPOINT` to run Apache in the
|
|||
|
foreground (i.e., as `PID 1`):
|
|||
|
|
|||
|
```
|
|||
|
FROM debian:stable
|
|||
|
RUN apt-get update && apt-get install -y --force-yes apache2
|
|||
|
EXPOSE 80 443
|
|||
|
VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
|
|||
|
ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
|
|||
|
```
|
|||
|
|
|||
|
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:
|
|||
|
|
|||
|
```bash
|
|||
|
#!/usr/bin/env bash
|
|||
|
set -e
|
|||
|
|
|||
|
if [ "$1" = 'postgres' ]; then
|
|||
|
chown -R postgres "$PGDATA"
|
|||
|
|
|||
|
if [ -z "$(ls -A "$PGDATA")" ]; then
|
|||
|
gosu postgres initdb
|
|||
|
fi
|
|||
|
|
|||
|
exec gosu postgres "$@"
|
|||
|
fi
|
|||
|
|
|||
|
exec "$@"
|
|||
|
```
|
|||
|
|
|||
|
Lastly, if you need to do some extra cleanup (or communicate with other containers)
|
|||
|
on shutdown, or are co-ordinating more than one executable, you may need to ensure
|
|||
|
that the `ENTRYPOINT` script receives the Unix signals, passes them on, and then
|
|||
|
does some more work:
|
|||
|
|
|||
|
```
|
|||
|
#!/bin/sh
|
|||
|
# Note: I've written this using sh so it works in the busybox container too
|
|||
|
|
|||
|
# USE the trap if you need to also do manual cleanup after the service is stopped,
|
|||
|
# or need to start multiple services in the one container
|
|||
|
trap "echo TRAPed signal" HUP INT QUIT TERM
|
|||
|
|
|||
|
# start service in background here
|
|||
|
/usr/sbin/apachectl start
|
|||
|
|
|||
|
echo "[hit enter key to exit] or run 'docker stop <container>'"
|
|||
|
read
|
|||
|
|
|||
|
# stop service and clean up here
|
|||
|
echo "stopping apache"
|
|||
|
/usr/sbin/apachectl stop
|
|||
|
|
|||
|
echo "exited $0"
|
|||
|
```
|
|||
|
|
|||
|
If you run this image with `docker run -it --rm -p 80:80 --name test apache`,
|
|||
|
you can then examine the container's processes with `docker exec`, or `docker top`,
|
|||
|
and then ask the script to stop Apache:
|
|||
|
|
|||
|
```bash
|
|||
|
$ docker exec -it test ps aux
|
|||
|
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
|
|||
|
root 1 0.1 0.0 4448 692 ? Ss+ 00:42 0:00 /bin/sh /run.sh 123 cmd cmd2
|
|||
|
root 19 0.0 0.2 71304 4440 ? Ss 00:42 0:00 /usr/sbin/apache2 -k start
|
|||
|
www-data 20 0.2 0.2 360468 6004 ? Sl 00:42 0:00 /usr/sbin/apache2 -k start
|
|||
|
www-data 21 0.2 0.2 360468 6000 ? Sl 00:42 0:00 /usr/sbin/apache2 -k start
|
|||
|
root 81 0.0 0.1 15572 2140 ? R+ 00:44 0:00 ps aux
|
|||
|
$ docker top test
|
|||
|
PID USER COMMAND
|
|||
|
10035 root {run.sh} /bin/sh /run.sh 123 cmd cmd2
|
|||
|
10054 root /usr/sbin/apache2 -k start
|
|||
|
10055 33 /usr/sbin/apache2 -k start
|
|||
|
10056 33 /usr/sbin/apache2 -k start
|
|||
|
$ /usr/bin/time docker stop test
|
|||
|
test
|
|||
|
real 0m 0.27s
|
|||
|
user 0m 0.03s
|
|||
|
sys 0m 0.03s
|
|||
|
```
|
|||
|
|
|||
|
> **Note:** you can override the `ENTRYPOINT` setting using `--entrypoint`,
|
|||
|
> but this can only set the binary to *exec* (no `sh -c` will be used).
|
|||
|
|
|||
|
> **Note**:
|
|||
|
> The *exec* form is parsed as a JSON array, which means that
|
|||
|
> you must use double-quotes (") around words not single-quotes (').
|
|||
|
|
|||
|
> **Note**:
|
|||
|
> Unlike the *shell* form, the *exec* form does not invoke a command shell.
|
|||
|
> This means that normal shell processing does not happen. For example,
|
|||
|
> `ENTRYPOINT [ "echo", "$HOME" ]` will not do variable substitution on `$HOME`.
|
|||
|
> If you want shell processing then either use the *shell* form or execute
|
|||
|
> a shell directly, for example: `ENTRYPOINT [ "sh", "-c", "echo $HOME" ]`.
|
|||
|
> When using the exec form and executing a shell directly, as in the case for
|
|||
|
> the shell form, it is the shell that is doing the environment variable
|
|||
|
> expansion, not docker.
|
|||
|
|
|||
|
### 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
|
|||
|
ENTRYPOINT exec top -b
|
|||
|
|
|||
|
When you run this image, you'll see the single `PID 1` process:
|
|||
|
|
|||
|
$ docker run -it --rm --name test top
|
|||
|
Mem: 1704520K used, 352148K free, 0K shrd, 0K buff, 140368121167873K cached
|
|||
|
CPU: 5% usr 0% sys 0% nic 94% idle 0% io 0% irq 0% sirq
|
|||
|
Load average: 0.08 0.03 0.05 2/98 6
|
|||
|
PID PPID USER STAT VSZ %VSZ %CPU COMMAND
|
|||
|
1 0 root R 3164 0% 0% top -b
|
|||
|
|
|||
|
Which will exit cleanly on `docker stop`:
|
|||
|
|
|||
|
$ /usr/bin/time docker stop test
|
|||
|
test
|
|||
|
real 0m 0.20s
|
|||
|
user 0m 0.02s
|
|||
|
sys 0m 0.04s
|
|||
|
|
|||
|
If you forget to add `exec` to the beginning of your `ENTRYPOINT`:
|
|||
|
|
|||
|
FROM ubuntu
|
|||
|
ENTRYPOINT top -b
|
|||
|
CMD --ignored-param1
|
|||
|
|
|||
|
You can then run it (giving it a name for the next step):
|
|||
|
|
|||
|
$ docker run -it --name test top --ignored-param2
|
|||
|
Mem: 1704184K used, 352484K free, 0K shrd, 0K buff, 140621524238337K cached
|
|||
|
CPU: 9% usr 2% sys 0% nic 88% idle 0% io 0% irq 0% sirq
|
|||
|
Load average: 0.01 0.02 0.05 2/101 7
|
|||
|
PID PPID USER STAT VSZ %VSZ %CPU COMMAND
|
|||
|
1 0 root S 3168 0% 0% /bin/sh -c top -b cmd cmd2
|
|||
|
7 1 root R 3164 0% 0% top -b
|
|||
|
|
|||
|
You can see from the output of `top` that the specified `ENTRYPOINT` is not `PID 1`.
|
|||
|
|
|||
|
If you then run `docker stop test`, the container will not exit cleanly - the
|
|||
|
`stop` command will be forced to send a `SIGKILL` after the timeout:
|
|||
|
|
|||
|
$ docker exec -it test ps aux
|
|||
|
PID USER COMMAND
|
|||
|
1 root /bin/sh -c top -b cmd cmd2
|
|||
|
7 root top -b
|
|||
|
8 root ps aux
|
|||
|
$ /usr/bin/time docker stop test
|
|||
|
test
|
|||
|
real 0m 10.19s
|
|||
|
user 0m 0.04s
|
|||
|
sys 0m 0.03s
|
|||
|
|
|||
|
### 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.
|
|||
|
|
|||
|
1. Dockerfile should specify at least one of `CMD` or `ENTRYPOINT` commands.
|
|||
|
|
|||
|
2. `ENTRYPOINT` should be defined when using the container as an executable.
|
|||
|
|
|||
|
3. `CMD` should be used as a way of defining default arguments for an `ENTRYPOINT` command
|
|||
|
or for executing an ad-hoc command in a container.
|
|||
|
|
|||
|
4. `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 ["/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*](https://docs.docker.com/engine/tutorials/dockervolumes/#/mount-a-host-directory-as-a-data-volume)
|
|||
|
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
|
|||
|
RUN mkdir /myvol
|
|||
|
RUN echo "hello world" > /myvol/greeting
|
|||
|
VOLUME /myvol
|
|||
|
|
|||
|
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 a `host-dir`
|
|||
|
parameter. You must specify the mountpoint when you create or run the container.
|
|||
|
|
|||
|
## 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`.
|
|||
|
|
|||
|
> **Warning**:
|
|||
|
> When the user doesn't have a primary group then the image (or the next
|
|||
|
> instructions) will be run with the `root` group.
|
|||
|
|
|||
|
> On Windows, the user must be created first if it's not a built-in account.
|
|||
|
> This can be done with the `net user` command called as part of a Dockerfile.
|
|||
|
|
|||
|
```Dockerfile
|
|||
|
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
|
|||
|
|
|||
|
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
|
|||
|
WORKDIR b
|
|||
|
WORKDIR c
|
|||
|
RUN pwd
|
|||
|
|
|||
|
The output of the final `pwd` command in this `Dockerfile` would be
|
|||
|
`/a/b/c`.
|
|||
|
|
|||
|
The `WORKDIR` instruction can resolve environment variables previously set using
|
|||
|
`ENV`. You can only use environment variables explicitly set in the `Dockerfile`.
|
|||
|
For example:
|
|||
|
|
|||
|
ENV DIRPATH /path
|
|||
|
WORKDIR $DIRPATH/$DIRNAME
|
|||
|
RUN pwd
|
|||
|
|
|||
|
The output of the final `pwd` command in this `Dockerfile` would be
|
|||
|
`/path/$DIRNAME`
|
|||
|
|
|||
|
## 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
|
|||
|
ARG user1
|
|||
|
ARG buildno
|
|||
|
...
|
|||
|
```
|
|||
|
|
|||
|
> **Warning:** It is not recommended to use build-time variables for
|
|||
|
> passing secrets like github keys, user credentials etc. Build-time variable
|
|||
|
> values are visible to any user of the image with the `docker history` command.
|
|||
|
|
|||
|
### Default values
|
|||
|
|
|||
|
An `ARG` instruction can optionally include a default value:
|
|||
|
|
|||
|
```
|
|||
|
FROM busybox
|
|||
|
ARG user1=someuser
|
|||
|
ARG buildno=1
|
|||
|
...
|
|||
|
```
|
|||
|
|
|||
|
If an `ARG` instruction has a default value and if there is no value passed
|
|||
|
at build-time, the builder uses the default.
|
|||
|
|
|||
|
### Scope
|
|||
|
|
|||
|
An `ARG` variable definition comes into effect from the line on which it is
|
|||
|
defined in the `Dockerfile` not from the argument's use on the command-line or
|
|||
|
elsewhere. For example, consider this Dockerfile:
|
|||
|
|
|||
|
```
|
|||
|
1 FROM busybox
|
|||
|
2 USER ${user:-some_user}
|
|||
|
3 ARG user
|
|||
|
4 USER $user
|
|||
|
...
|
|||
|
```
|
|||
|
A user builds this file by calling:
|
|||
|
|
|||
|
```
|
|||
|
$ docker build --build-arg user=what_user .
|
|||
|
```
|
|||
|
|
|||
|
The `USER` at line 2 evaluates to `some_user` as the `user` variable is defined on the
|
|||
|
subsequent line 3. The `USER` at line 4 evaluates to `what_user` as `user` is
|
|||
|
defined and the `what_user` value was passed on the command line. Prior to its definition by an
|
|||
|
`ARG` instruction, any use of a variable results in an empty string.
|
|||
|
|
|||
|
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
|
|||
|
ARG SETTINGS
|
|||
|
RUN ./run/setup $SETTINGS
|
|||
|
|
|||
|
FROM busybox
|
|||
|
ARG SETTINGS
|
|||
|
RUN ./run/other $SETTINGS
|
|||
|
```
|
|||
|
|
|||
|
### Using ARG variables
|
|||
|
|
|||
|
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.
|
|||
|
|
|||
|
```
|
|||
|
1 FROM ubuntu
|
|||
|
2 ARG CONT_IMG_VER
|
|||
|
3 ENV CONT_IMG_VER v1.0.0
|
|||
|
4 RUN echo $CONT_IMG_VER
|
|||
|
```
|
|||
|
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` This behavior is similar to a shell
|
|||
|
script where a locally scoped variable overrides the variables passed as
|
|||
|
arguments or inherited from environment, from its point of definition.
|
|||
|
|
|||
|
Using the example above but a different `ENV` specification you can create more
|
|||
|
useful interactions between `ARG` and `ENV` instructions:
|
|||
|
|
|||
|
```
|
|||
|
1 FROM ubuntu
|
|||
|
2 ARG CONT_IMG_VER
|
|||
|
3 ENV CONT_IMG_VER ${CONT_IMG_VER:-v1.0.0}
|
|||
|
4 RUN echo $CONT_IMG_VER
|
|||
|
```
|
|||
|
|
|||
|
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.
|
|||
|
|
|||
|
The variable expansion technique in this example allows you to pass arguments
|
|||
|
from the command line and persist them in the final image by leveraging the
|
|||
|
`ENV` instruction. Variable expansion is only supported for [a limited set of
|
|||
|
Dockerfile instructions.](#environment-replacement)
|
|||
|
|
|||
|
### 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, simply pass them on the command line using the flag:
|
|||
|
|
|||
|
```
|
|||
|
--build-arg <varname>=<value>
|
|||
|
```
|
|||
|
|
|||
|
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.
|
|||
|
|
|||
|
For example, consider building the following Dockerfile using
|
|||
|
`--build-arg HTTP_PROXY=http://user:pass@proxy.lon.example.com`
|
|||
|
|
|||
|
``` Dockerfile
|
|||
|
FROM ubuntu
|
|||
|
RUN echo "Hello World"
|
|||
|
```
|
|||
|
|
|||
|
In this case, the value of the `HTTP_PROXY` variable is not available in the
|
|||
|
`docker history` and is not cached. If you were to change location, and your
|
|||
|
proxy server changed to `http://user:pass@proxy.sfo.example.com`, a subsequent
|
|||
|
build does not result in a cache miss.
|
|||
|
|
|||
|
If you need to override this behaviour then you may do so by adding an `ARG`
|
|||
|
statement in the Dockerfile as follows:
|
|||
|
|
|||
|
``` Dockerfile
|
|||
|
FROM ubuntu
|
|||
|
ARG HTTP_PROXY
|
|||
|
RUN echo "Hello World"
|
|||
|
```
|
|||
|
|
|||
|
When building this Dockerfile, the `HTTP_PROXY` is preserved in the
|
|||
|
`docker history`, and changing its value invalidates the build cache.
|
|||
|
|
|||
|
### Impact on build caching
|
|||
|
|
|||
|
`ARG` variables are not persisted into the built image as `ENV` variables are.
|
|||
|
However, `ARG` variables do impact the build cache in similar ways. If a
|
|||
|
Dockerfile defines an `ARG` variable whose value is different from a previous
|
|||
|
build, then a "cache miss" occurs upon its first usage, not its definition. In
|
|||
|
particular, all `RUN` instructions following an `ARG` instruction use the `ARG`
|
|||
|
variable implicitly (as an environment variable), thus can cause a cache miss.
|
|||
|
All predefined `ARG` variables are exempt from caching unless there is a
|
|||
|
matching `ARG` statement in the `Dockerfile`.
|
|||
|
|
|||
|
For example, consider these two Dockerfile:
|
|||
|
|
|||
|
```
|
|||
|
1 FROM ubuntu
|
|||
|
2 ARG CONT_IMG_VER
|
|||
|
3 RUN echo $CONT_IMG_VER
|
|||
|
```
|
|||
|
|
|||
|
```
|
|||
|
1 FROM ubuntu
|
|||
|
2 ARG CONT_IMG_VER
|
|||
|
3 RUN echo hello
|
|||
|
```
|
|||
|
|
|||
|
If you specify `--build-arg CONT_IMG_VER=<value>` on the command line, in both
|
|||
|
cases, the specification on line 2 does not cause a cache miss; line 3 does
|
|||
|
cause a cache miss.`ARG CONT_IMG_VER` causes the RUN line to be identified
|
|||
|
as the same as running `CONT_IMG_VER=<value>` echo hello, so if the `<value>`
|
|||
|
changes, we get a cache miss.
|
|||
|
|
|||
|
Consider another example under the same command line:
|
|||
|
|
|||
|
```
|
|||
|
1 FROM ubuntu
|
|||
|
2 ARG CONT_IMG_VER
|
|||
|
3 ENV CONT_IMG_VER $CONT_IMG_VER
|
|||
|
4 RUN echo $CONT_IMG_VER
|
|||
|
```
|
|||
|
In this example, the cache miss occurs on line 3. The miss happens because
|
|||
|
the variable's value in the `ENV` references the `ARG` variable and that
|
|||
|
variable is changed through the command line. In this example, the `ENV`
|
|||
|
command causes the image to include the value.
|
|||
|
|
|||
|
If an `ENV` instruction overrides an `ARG` instruction of the same name, like
|
|||
|
this Dockerfile:
|
|||
|
|
|||
|
```
|
|||
|
1 FROM ubuntu
|
|||
|
2 ARG CONT_IMG_VER
|
|||
|
3 ENV CONT_IMG_VER hello
|
|||
|
4 RUN echo $CONT_IMG_VER
|
|||
|
```
|
|||
|
|
|||
|
Line 3 does not cause a cache miss because the value of `CONT_IMG_VER` is a
|
|||
|
constant (`hello`). As a result, the environment variables and values used on
|
|||
|
the `RUN` (line 4) doesn't change between builds.
|
|||
|
|
|||
|
## 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 `Dockerfile` to copy-paste into their application, but
|
|||
|
that is inefficient, error-prone and difficult to update because it
|
|||
|
mixes with application-specific code.
|
|||
|
|
|||
|
The solution is to use `ONBUILD` to register advance instructions to
|
|||
|
run later, during the next build stage.
|
|||
|
|
|||
|
Here's how it works:
|
|||
|
|
|||
|
1. 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.
|
|||
|
2. 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
|
|||
|
the `docker inspect` command.
|
|||
|
3. Later the image may be used as a base for a new build, using the
|
|||
|
`FROM` instruction. As part of processing the `FROM` instruction,
|
|||
|
the downstream builder looks for `ONBUILD` triggers, and executes
|
|||
|
them in the same order they were registered. If any of the triggers
|
|||
|
fail, the `FROM` instruction is aborted which in turn causes the
|
|||
|
build to fail. If all triggers succeed, the `FROM` instruction
|
|||
|
completes and the build continues as usual.
|
|||
|
4. 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
|
|||
|
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
|
|||
|
[...]
|
|||
|
|
|||
|
> **Warning**: Chaining `ONBUILD` instructions using `ONBUILD ONBUILD` isn't allowed.
|
|||
|
|
|||
|
> **Warning**: The `ONBUILD` instruction may not trigger `FROM` or `MAINTAINER` instructions.
|
|||
|
|
|||
|
## 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 valid unsigned number that matches a position in the kernel's syscall table, for instance 9,
|
|||
|
or a signal name in the format SIGNAME, for instance SIGKILL.
|
|||
|
|
|||
|
## 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`)
|
|||
|
|
|||
|
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 after the `CMD` keyword can be either a shell command (e.g. `HEALTHCHECK
|
|||
|
CMD /bin/check-running`) or an _exec_ array (as with other Dockerfile commands;
|
|||
|
see e.g. `ENTRYPOINT` for details).
|
|||
|
|
|||
|
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 \
|
|||
|
CMD curl -f http://localhost/ || exit 1
|
|||
|
|
|||
|
To help debug failing probes, any output text (UTF-8 encoded) that the command writes
|
|||
|
on stdout or stderr will be stored in the health status and can be queried with
|
|||
|
`docker inspect`. Such output should be kept short (only the first 4096 bytes
|
|||
|
are stored currently).
|
|||
|
|
|||
|
When the health status of a container changes, a `health_status` event is
|
|||
|
generated with the new status.
|
|||
|
|
|||
|
The `HEALTHCHECK` feature was added in Docker 1.12.
|
|||
|
|
|||
|
|
|||
|
## 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
|
|||
|
|
|||
|
# Executed as cmd /S /C echo default
|
|||
|
RUN echo default
|
|||
|
|
|||
|
# Executed as cmd /S /C powershell -command Write-Host default
|
|||
|
RUN powershell -command Write-Host default
|
|||
|
|
|||
|
# Executed as powershell -command Write-Host hello
|
|||
|
SHELL ["powershell", "-command"]
|
|||
|
RUN Write-Host hello
|
|||
|
|
|||
|
# Executed as cmd /S /C echo hello
|
|||
|
SHELL ["cmd", "/S"", "/C"]
|
|||
|
RUN echo hello
|
|||
|
|
|||
|
The following instructions can be affected by the `SHELL` instruction when the
|
|||
|
*shell* form of them is used in a Dockerfile: `RUN`, `CMD` and `ENTRYPOINT`.
|
|||
|
|
|||
|
The following example is a common pattern found on Windows which can be
|
|||
|
streamlined by using the `SHELL` instruction:
|
|||
|
|
|||
|
...
|
|||
|
RUN powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
|
|||
|
...
|
|||
|
|
|||
|
The command invoked by docker will be:
|
|||
|
|
|||
|
cmd /S /C powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
|
|||
|
|
|||
|
This is inefficient for two reasons. First, there is an un-necessary cmd.exe command
|
|||
|
processor (aka shell) being invoked. Second, each `RUN` instruction in the *shell*
|
|||
|
form requires an extra `powershell -command` prefixing the command.
|
|||
|
|
|||
|
To make this more efficient, one of two mechanisms can be employed. One is to
|
|||
|
use the JSON form of the RUN command such as:
|
|||
|
|
|||
|
...
|
|||
|
RUN ["powershell", "-command", "Execute-MyCmdlet", "-param1 \"c:\\foo.txt\""]
|
|||
|
...
|
|||
|
|
|||
|
While the JSON form is unambiguous and does not use the un-necessary cmd.exe,
|
|||
|
it does require more verbosity through double-quoting and escaping. The alternate
|
|||
|
mechanism is to use the `SHELL` instruction and the *shell* form,
|
|||
|
making a more natural syntax for Windows users, especially when combined with
|
|||
|
the `escape` parser directive:
|
|||
|
|
|||
|
# escape=`
|
|||
|
|
|||
|
FROM microsoft/nanoserver
|
|||
|
SHELL ["powershell","-command"]
|
|||
|
RUN New-Item -ItemType Directory C:\Example
|
|||
|
ADD Execute-MyCmdlet.ps1 c:\example\
|
|||
|
RUN c:\example\Execute-MyCmdlet -sample 'hello world'
|
|||
|
|
|||
|
Resulting in:
|
|||
|
|
|||
|
PS E:\docker\build\shell> docker build -t shell .
|
|||
|
Sending build context to Docker daemon 4.096 kB
|
|||
|
Step 1/5 : FROM microsoft/nanoserver
|
|||
|
---> 22738ff49c6d
|
|||
|
Step 2/5 : SHELL powershell -command
|
|||
|
---> Running in 6fcdb6855ae2
|
|||
|
---> 6331462d4300
|
|||
|
Removing intermediate container 6fcdb6855ae2
|
|||
|
Step 3/5 : RUN New-Item -ItemType Directory C:\Example
|
|||
|
---> Running in d0eef8386e97
|
|||
|
|
|||
|
|
|||
|
Directory: C:\
|
|||
|
|
|||
|
|
|||
|
Mode LastWriteTime Length Name
|
|||
|
---- ------------- ------ ----
|
|||
|
d----- 10/28/2016 11:26 AM Example
|
|||
|
|
|||
|
|
|||
|
---> 3f2fbf1395d9
|
|||
|
Removing intermediate container d0eef8386e97
|
|||
|
Step 4/5 : ADD Execute-MyCmdlet.ps1 c:\example\
|
|||
|
---> a955b2621c31
|
|||
|
Removing intermediate container b825593d39fc
|
|||
|
Step 5/5 : RUN c:\example\Execute-MyCmdlet 'hello world'
|
|||
|
---> Running in be6d8e63fe75
|
|||
|
hello world
|
|||
|
---> 8e559e9bf424
|
|||
|
Removing intermediate container be6d8e63fe75
|
|||
|
Successfully built 8e559e9bf424
|
|||
|
PS E:\docker\build\shell>
|
|||
|
|
|||
|
The `SHELL` instruction could also be used to modify the way in which
|
|||
|
a shell operates. For example, using `SHELL cmd /S /C /V:ON|OFF` on Windows, delayed
|
|||
|
environment variable expansion semantics could be modified.
|
|||
|
|
|||
|
The `SHELL` instruction can also be used on Linux should an alternate shell be
|
|||
|
required such as `zsh`, `csh`, `tcsh` and others.
|
|||
|
|
|||
|
The `SHELL` feature was added in Docker 1.12.
|
|||
|
|
|||
|
## Dockerfile examples
|
|||
|
|
|||
|
Below you can see some examples of Dockerfile syntax. If you're interested in
|
|||
|
something more realistic, take a look at the list of [Dockerization examples](https://docs.docker.com/engine/examples/).
|
|||
|
|
|||
|
```
|
|||
|
# Nginx
|
|||
|
#
|
|||
|
# VERSION 0.0.1
|
|||
|
|
|||
|
FROM ubuntu
|
|||
|
LABEL Description="This image is used to start the foobar executable" Vendor="ACME Products" Version="1.0"
|
|||
|
RUN apt-get update && apt-get install -y inotify-tools nginx apache2 openssh-server
|
|||
|
```
|
|||
|
|
|||
|
```
|
|||
|
# Firefox over VNC
|
|||
|
#
|
|||
|
# VERSION 0.3
|
|||
|
|
|||
|
FROM ubuntu
|
|||
|
|
|||
|
# Install vnc, xvfb in order to create a 'fake' display and firefox
|
|||
|
RUN apt-get update && apt-get install -y x11vnc xvfb firefox
|
|||
|
RUN mkdir ~/.vnc
|
|||
|
# Setup a password
|
|||
|
RUN x11vnc -storepasswd 1234 ~/.vnc/passwd
|
|||
|
# Autostart firefox (might not be the best way, but it does the trick)
|
|||
|
RUN bash -c 'echo "firefox" >> /.bashrc'
|
|||
|
|
|||
|
EXPOSE 5900
|
|||
|
CMD ["x11vnc", "-forever", "-usepw", "-create"]
|
|||
|
```
|
|||
|
|
|||
|
```
|
|||
|
# Multiple images example
|
|||
|
#
|
|||
|
# VERSION 0.1
|
|||
|
|
|||
|
FROM ubuntu
|
|||
|
RUN echo foo > bar
|
|||
|
# Will output something like ===> 907ad6c2736f
|
|||
|
|
|||
|
FROM ubuntu
|
|||
|
RUN echo moo > oink
|
|||
|
# Will output something like ===> 695d7793cbe4
|
|||
|
|
|||
|
# You'll now have two images, 907ad6c2736f with /bar, and 695d7793cbe4 with
|
|||
|
# /oink.
|
|||
|
```
|