dockerdockerfiledocker-multi-stage-build

Share variable in multi-stage Dockerfile: ARG before FROM not substituted


I'm writing a multi-stage Dockerfile for the darshan utils:

ARG DARSHAN_VER=3.1.6

FROM fedora:29 as build
RUN dnf install -y \
        gcc \
        make \
        bzip2 bzip2-devel zlib zlib-devel
RUN curl -O "ftp://ftp.mcs.anl.gov/pub/darshan/releases/darshan-${DARSHAN_VER}.tar.gz" \
    && tar ...


FROM fedora:29
COPY --from=build "/usr/local/darshan-${DARSHAN_VER}" "/usr/local/darshan-${DARSHAN_VER}"
...

I build it with docker build -t darshan-util:3.6.1 . and the error I get is:

Step 5/10 : RUN curl -O "ftp://ftp.mcs.anl.gov/pub/darshan/releases/darshan-${DARSHAN_VER}.tar.gz"     && tar ...

 ---> Running in 9943cce1669c
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
...
curl: (78) RETR response: 550
The command '/bin/sh -c curl -O "ftp://ftp.mcs.anl.gov/pub/darshan/releases/darshan-${DARSHAN_VER}.tar.gz"     && tar ...' returned a non-zero code: 78

I'd like to reuse the same ARG in both stages, so that I can define a default build variable just once. If I duplicate ARG in both stages, just below the two FROMs, it builds correctly.

What is the correct way to define a "global" multi-stage ARG variable with a default?


Solution

  • ARGs only last for the build phase of a single image. For the multistage, renew the ARG by simply stating:

    ARG DARSHAN_VER
    

    after your FROM instructions.

    cf. https://docs.docker.com/engine/reference/builder/#arg

    ARG DARSHAN_VER=3.1.6
    
    FROM fedora:29 as build
    ARG DARSHAN_VER
    RUN dnf install -y \
            gcc \
            make \
            bzip2 bzip2-devel zlib zlib-devel
    RUN curl -O "ftp://ftp.mcs.anl.gov/pub/darshan/releases/darshan-${DARSHAN_VER}.tar.gz" \
        && tar ...
    
    
    FROM fedora:29
    ARG DARSHAN_VER
    COPY --from=build "/usr/local/darshan-${DARSHAN_VER}" "/usr/local/darshan-${DARSHAN_VER}"
    ...
    

    You will notice how I declared the initial value at the top of the script, and pull it in on each image.