Home > OS >  redeclared ARG in multistage builds is not recognized properly
redeclared ARG in multistage builds is not recognized properly

Time:12-30

Here is my snippet Dockerfile depicting the problem:

FROM alpine:latest as build

ARG APP_PATH="/etc/app"
RUN echo ${APP_PATH}
RUN mkdir -p "${APP_PATH}"

FROM alpine:latest

ARG APP_PATH
RUN echo ${APP_PATH}
COPY --from=build ["${APP_PATH}", "${APP_PATH}"]

When building the above script by issuing docker build -t test --progress=plain --no-cache ., I get the following output (less important parts were skipped for clarity):

#5 [stage-1 2/3] RUN echo ${APP_PATH}
#5 sha256:73371d6fc2be023711564bc13780f5e461c3fe7487db608b727f1d4babde1b70
#5 0.582
#5 DONE 0.6s

#6 [build 2/3] RUN echo /etc/app
#6 sha256:6754d7b8e161e8b0ce71d4d8a656d4387a4fe7fbc4f49ad356b566485304a166
#6 0.559 /etc/app
#6 DONE 0.6s

#7 [build 3/3] RUN mkdir -p "/etc/app"
#7 sha256:d28870e7fc31e083bdbd495f7d2af4e27cf848146d0f02485655605ddf6e3b7f
#7 DONE 0.9s

#8 [stage-1 3/3] COPY --from=build [, ]
#8 sha256:31f75603635b8a58e1179974610938cc37a14813ec186ba638affb1a494a51b1
#8 DONE 0.1s

During the first "build" stage, Docker correctly recognizes the APP_PATH argument - we can see that the issued RUN commands have ${APP_PATH} replaced with the proper string which is /etc/app. On the other hand, in the next stage it seems that the argument is presumably mistakenly taken as an environmental variable which, of course, does not exist, as it was never defined. However, from what I've read from the docs, to restore previously declared ARG in subsequent build stages all I need to do is to redeclare it in the stages where they are required and it should be visible there. What is wrong with my understanding?

CodePudding user response:

This was happened because scope ARG declaration. you can not access to an ARG that defined in another scope.

You must define ARG before FROM and use it in scopes like this

ARG APP_PATH="/etc/app"

FROM alpine:latest as build

ARG APP_PATH
RUN echo ${APP_PATH}
RUN mkdir -p "${APP_PATH}"

FROM alpine:latest

ARG APP_PATH
RUN echo ${APP_PATH}
COPY --from=build ["${APP_PATH}", "${APP_PATH}"]

After running docker build -t test --progress=plain --no-cache . the output is:

Sending build context to Docker daemon  2.048kB
Step 1/9 : ARG APP_PATH="/etc/app"
Step 2/9 : FROM alpine:latest as build
 ---> 49176f190c7e
Step 3/9 : ARG APP_PATH
 ---> Running in 4af7158268ee
Removing intermediate container 4af7158268ee
 ---> de0d596ce407
Step 4/9 : RUN echo ${APP_PATH}
 ---> Running in 3a5f3963d620
/etc/app
Removing intermediate container 3a5f3963d620
 ---> 9b259c76e9d5
Step 5/9 : RUN mkdir -p "${APP_PATH}"
 ---> Running in 391fddbfe692
Removing intermediate container 391fddbfe692
 ---> 28b9fe9eacbc
Step 6/9 : FROM alpine:latest
 ---> 49176f190c7e
Step 7/9 : ARG APP_PATH
 ---> Running in 8c20d67176ce
Removing intermediate container 8c20d67176ce
 ---> aa2b9e7dec83
Step 8/9 : RUN echo ${APP_PATH}
 ---> Running in eeb06ceedcb0
/etc/app
Removing intermediate container eeb06ceedcb0
 ---> 8aa31919ee1c
Step 9/9 : COPY --from=build ["${APP_PATH}", "${APP_PATH}"]
 ---> 0af04606799b
Successfully built 0af04606799b
Successfully tagged test:latest
  • Related