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>
This commit is contained in:
Madhav Puri 2014-11-14 10:59:14 -08:00 committed by Tibor Vass
parent 8bdf17d8fe
commit 40a2dac738
4 changed files with 280 additions and 0 deletions

View File

@ -966,6 +966,127 @@ For example:
The output of the final `pwd` command in this `Dockerfile` would be The output of the final `pwd` command in this `Dockerfile` would be
`/path/$DIRNAME` `/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 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
ONBUILD [INSTRUCTION] ONBUILD [INSTRUCTION]

View File

@ -17,6 +17,7 @@ weight=1
-f, --file="" Name of the Dockerfile (Default is 'PATH/Dockerfile') -f, --file="" Name of the Dockerfile (Default is 'PATH/Dockerfile')
--force-rm=false Always remove intermediate containers --force-rm=false Always remove intermediate containers
--build-arg=[] Set build-time variables
--no-cache=false Do not use cache when building the image --no-cache=false Do not use cache when building the image
--pull=false Always attempt to pull a newer version of the image --pull=false Always attempt to pull a newer version of the image
-q, --quiet=false Suppress the verbose output generated by the containers -q, --quiet=false Suppress the verbose output generated by the containers
@ -251,3 +252,22 @@ flag](/reference/run/#specifying-custom-cgroups).
Using the `--ulimit` option with `docker build` will cause each build step's Using the `--ulimit` option with `docker build` will cause each build step's
container to be started using those [`--ulimit` container to be started using those [`--ulimit`
flag values](/reference/run/#setting-ulimits-in-a-container). flag values](/reference/run/#setting-ulimits-in-a-container).
You can use `ENV` instructions in a Dockerfile to define variable
values. These values persist in the built image. However, often
persistence is not what you want. Users want to specify variables differently
depending on which host they build an image on.
A good example is `http_proxy` or source versions for pulling intermediate
files. The `ARG` instruction lets Dockerfile authors define values that users
can set at build-time using the `---build-arg` flag:
$ docker build --build-arg HTTP_PROXY=http://10.20.30.2:1234 .
This flag allows you to pass the build-time variables that are
accessed like regular environment variables in the `RUN` instruction of the
Dockerfile. Also, these values don't persist in the intermediate or final images
like `ENV` values do.
For detailed information on using `ARG` and `ENV` instructions, see the
[Dockerfile reference](/reference/builder).

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**. 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**
-- `ONBUILD [INSTRUCTION]` -- `ONBUILD [INSTRUCTION]`
The **ONBUILD** instruction adds a trigger instruction to an image. The 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** **docker build**
[**--help**] [**--help**]
[**-f**|**--file**[=*PATH/Dockerfile*]] [**-f**|**--file**[=*PATH/Dockerfile*]]
[**--build-arg**[=*[]*]]
[**--force-rm**[=*false*]] [**--force-rm**[=*false*]]
[**--no-cache**[=*false*]] [**--no-cache**[=*false*]]
[**--pull**[=*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 remote context. In all cases, the file must be within the build context.
The default is *Dockerfile*. 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* **--force-rm**=*true*|*false*
Always remove intermediate containers, even after unsuccessful builds. The default is *false*. Always remove intermediate containers, even after unsuccessful builds. The default is *false*.