-
Notifications
You must be signed in to change notification settings - Fork 18.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature Request] Support any number of ARG
being declared before FROM
and available during build
#37622
Comments
ARG
being declared before FROM
ARG
being declared before FROM
and available during build
Thanks for opening this request! Let me start with "layers"; in Docker before version 1.10, any Dockerfile instruction created a new container; the Dockerfile instruction (wether it be Docker created a chain or "parent" images, and when pushing (or pulling) the final image, all intermediate images had to be pushed, or pulled, even if a Dockerfile instruction did not make filesystem changes (e.g. also in case that only a change to the metadata ( Docker 1.10 and up uses a new, content-addressable store. The new store does keep track of intermediate images during build (so that you can The builder is also "smart" enough to decide if a new layer has to be created; if a Dockerfile instruction doesn't make changes to the container's filesystem, then only the metadata is updated, and no new layer is created. For example, this Dockerfile only has a single layer: ARG BASE=busybox:latest
FROM $BASE
ENV foobar=baz
ENV hello=world
VOLUME /something
LABEL iam=a-label
ENTRYPOINT ["/bin/sh"]
CMD ["-c", "echo hello"] $ docker build -t foo .
$ docker image inspect --format='{{json .RootFS}}' foo
{
"Type": "layers",
"Layers": [
"sha256:f9d9e4e6e2f0689cd752390e14ade48b0ec6f2a488a05af5ab2f9ccaf54c299d"
]
} So, while combining (for example) multiple
This is really by design; build stages should be scoped, independent. Globally defined (before the first Because of this design, it's possible to globally define a build-arg, but only consume it in some build-stages. It also allow (even more so in the next builder, powered by BuildKit) to build stages in parallel (the builder creates a dependency graph, and based on that performs stages in parallel, or even skips stages if they're not needed for the final image). Yes; this design requires you to define every
(Following the explanation above); doing so would force the build to always be done sequential; no "following stage" can start until all previous stages were executed (because they potentially modify the value of an So, how to re-use a globally defined build-arg in multiple stagesA globally defined build-arg can be used in a stage by declaring it inside that stage. If you want to inherit the value that's set globally, omit a value, and the For example; the following Dockerfile: # default value for `FOO`
ARG FOO=bar
# no default value
ARG BAR
FROM busybox
ARG FOO
# only $FOO is set in this stage
RUN echo $FOO; echo $BAR
FROM busybox
ARG FOO
ARG BAR
# both $FOO and $BAR are set in this stage
RUN echo $FOO; echo $BAR
FROM busybox
ARG FOO="default for this stage"
ARG BAR
# both $FOO and $BAR are set in this stage
RUN echo $FOO; echo $BAR
FROM busybox
ENV FOO="I am an env"
ARG BAR="default for this stage but overridden"
# both $FOO and $BAR are set in this stage
RUN echo $FOO; echo $BAR docker build --no-cache --build-arg BAR="command-line value" -t foo .
Step 1/17 : ARG FOO=bar
Step 2/17 : ARG BAR
Step 3/17 : FROM busybox
---> e1ddd7948a1c
Step 4/17 : ARG FOO
---> Running in 9dcdf1666365
Removing intermediate container 9dcdf1666365
---> e280ff0655db
Step 5/17 : RUN echo $FOO; echo $BAR
---> Running in 42d999bb0e24
bar
Removing intermediate container 42d999bb0e24
---> c1513a5bad04
Step 6/17 : FROM busybox
---> e1ddd7948a1c
Step 7/17 : ARG FOO
---> Running in f533eb867ee3
Removing intermediate container f533eb867ee3
---> f8108c428e99
Step 8/17 : ARG BAR
---> Running in bbe3af4236d9
Removing intermediate container bbe3af4236d9
---> d99dd8158aec
Step 9/17 : RUN echo $FOO; echo $BAR
---> Running in aa5b02eba9a2
bar
command-line value
Removing intermediate container aa5b02eba9a2
---> 1452606ca620
Step 10/17 : FROM busybox
---> e1ddd7948a1c
Step 11/17 : ARG FOO="default for this stage"
---> Running in 86dcdd11ac14
Removing intermediate container 86dcdd11ac14
---> 5010924fc5ce
Step 12/17 : ARG BAR
---> Running in e83a57b16402
Removing intermediate container e83a57b16402
---> 43fffe5388d6
Step 13/17 : RUN echo $FOO; echo $BAR
---> Running in a2eb9624ad0b
default for this stage
command-line value
Removing intermediate container a2eb9624ad0b
---> e97abc690b75
Step 14/17 : FROM busybox
---> e1ddd7948a1c
Step 15/17 : ENV FOO="I am an env"
---> Running in c5a74b625158
Removing intermediate container c5a74b625158
---> dde4eb645836
Step 16/17 : ARG BAR="default for this stage but overridden"
---> Running in 084f854fc113
Removing intermediate container 084f854fc113
---> c22dcc4c81ae
Step 17/17 : RUN echo $FOO; echo $BAR
---> Running in 0c656c75ed35
I am an env
command-line value
Removing intermediate container 0c656c75ed35
---> e434a711f19e
Successfully built e434a711f19e
Successfully tagged foo:latest Inspecting the image shows that it still consists of a single layer; $ docker image inspect --format='{{json .RootFS}}' foo
{
"Type": "layers",
"Layers": [
"sha256:f9d9e4e6e2f0689cd752390e14ade48b0ec6f2a488a05af5ab2f9ccaf54c299d"
]
} |
Thanks so much for your reply and it's great to find out there is no need to change anything :) |
Once parameters support have been introduced into
FROM
instruction throughARG
, I think the following will improve consistency and enable reducing the number of layers in our images.Consider the following Dockerfie:
You'll get the following build output:
and image's labels:
You can see that the same
ARG
instruction have different behaviors:CENTOS_VERSION
will only be visible toFROM
instruction but not to any following instructionCENTOS_VERSION
instruction will create no new layer in the resulting imageMY_TAG
will be available for any following build containerMY_TAG
instruction will imply the creation of a new layer and multiple of them can't be merged into one asENV
( Multiline ARG - docker failed to build: ARG requires exactly one argument #35950 )This behavior is problematic for the following reasons:
CENTOS_VERSION
in my image without duplicating the instruction declaration afterFROM
, introducing inconsistency risks and complexityARG
being a build argument, I don't see a strong need to generate a layer for each of them (e.g.: we don't generate new layers for proxy configuration)What I propose is:
ARG
instructions to be declared beforeFROM
and make them available to instructions followingFROM
ARG
instructions declared afterFROM
can remain supported for backward compatibility purposes but I'd encourage the new behavior.I think it would bring the following benefits:
ARG
beforeFROM
.ARG
andENV
which I see colleagues being confused about them.ARG
values could be available to all stages of multi-stage build.Docker versions (Docker Toolbox in Win 8.1):
The text was updated successfully, but these errors were encountered: