Support for passing build-time variables in build context

- The build-time variables are passed as environment-context for command(s)
run as part of the RUN primitve. These variables are not persisted in environment of
intermediate and final images when passed as context for RUN. The build environment
is prepended to the intermediate continer's command string for aiding cache lookups.
It also helps with build traceability. But this also makes the feature less secure from
point of view of passing build time secrets.

- The build-time variables also get used to expand the symbols used in certain
Dockerfile primitves like ADD, COPY, USER etc, without an explicit prior definiton using a
ENV primitive. These variables get persisted in the intermediate and final images
whenever they are expanded.

- The build-time variables are only expanded or passed to the RUN primtive if they
are defined in Dockerfile using the ARG primitive or belong to list of built-in variables.
HTTP_PROXY, HTTPS_PROXY, http_proxy, https_proxy, FTP_PROXY and NO_PROXY are built-in
variables that needn't be explicitly defined in Dockerfile to use this feature.

Signed-off-by: Madhav Puri <madhav.puri@gmail.com>
Upstream-commit: 54240f8da9992880e20a1508e9a6f0e59f2adef1
Component: engine
This commit is contained in:
Madhav Puri
2014-11-14 10:59:14 -08:00
parent be5aed80c9
commit ded3de600a
18 changed files with 1106 additions and 57 deletions

View File

@ -317,6 +317,126 @@ A Dockerfile is similar to a Makefile.
In the above example, the output of the **pwd** command is **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 an error.
```
One or more build-args were not consumed, failing build.
```
The Dockerfile author can define a single variable by specifying `ARG` once or many
variables by specifying `ARG` more than once. For example, a valid Dockerfile:
```
FROM busybox
ARG user1
ARG buildno
...
```
A Dockerfile author may optionally specify a default value for an `ARG` instruction:
```
FROM busybox
ARG user1=someuser
ARG buildno=1
...
```
If an `ARG` value has a default and if there is no value passed at build-time, the
builder uses the default.
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 Dockerfile
```
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.
> **Note:** It is not recommended to use build-time variables for
> passing secrets like github keys, user credentials etc.
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 Dockerfile
```
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
```
The command line passes the `--build-arg` and sets the `v2.0.1` value. And the `ARG
CONT_IMG_VER` is defined on line 2 of the Dockerfile. On line 3, the `ENV`
instruction of the same name resolves to `v2.0.1` as the build-time variable
was passed from the command line and expanded here.
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 the `Dockerfile` instructions
described [here](#environment-replacement).
Unlike an `ARG` instruction, `ENV` values are always persisted in the built image. If
`docker build` were run without setting the `--build-arg` flag, then
`CONT_IMG_VER` is still persisted in the image but its value would be `v1.0.0`.
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 `--build-arg
<varname>=<value>` flag.
**ONBUILD**
-- `ONBUILD [INSTRUCTION]`
The **ONBUILD** instruction adds a trigger instruction to an image. The

View File

@ -8,6 +8,7 @@ docker-build - Build a new image from the source code at PATH
**docker build**
[**--help**]
[**-f**|**--file**[=*PATH/Dockerfile*]]
[**--build-arg**[=*[]*]]
[**--force-rm**[=*false*]]
[**--no-cache**[=*false*]]
[**--pull**[=*false*]]
@ -51,6 +52,24 @@ cloned locally and then sent as the context.
the remote context. In all cases, the file must be within the build context.
The default is *Dockerfile*.
**--build-arg**=*variable*
Set value for build-time variable. This option allows you to specify
values of the variables that are available for expansion/substitution in the
Dockerfile instructions like ADD, COPY etc, without an explicit prior definition by
the ENV instruction. The build-time variables are also passed as environment
context for the command(s) that will be executed as part of RUN instruction
of Dockerfile, if there is no explicit prior definition by the ENV instruction.
Normally, these variables are not persisted in the resulting Docker image. This gives
the flexibility to build an image by passing host specific environment variables (like
http_proxy) that will be used on the RUN commands without affecting portability
of the generated image.
However, as with any variable, they can be persisted in the final image if they are used in an
ENV instruction (e.g. ENV myName=$myName will save myName in the image).
Only the build-time variables that are defined using the ARG instruction of Dockerfile
are allowed to be expanded or passed as environment to the RUN command. Read more about
ARG instruction in Dockerfile reference.
**--force-rm**=*true*|*false*
Always remove intermediate containers, even after unsuccessful builds. The default is *false*.