dockercopydockerfile

Specify multiple files in ARG to COPY in Dockerfile


Consider the following docker build context:

src/
  hi
  there
  bye

and Dockerfile:

FROM ubuntu

RUN mkdir test
COPY src/hi src/there test/

This works just fine but I would like to make the list of files to copy an ARG, something like:

FROM ubuntu

ARG files

RUN mkdir test
COPY ${files} test/

Unfortunately calling with docker build --build-arg files='src/hi src/there' some_path fails because it treats src/hi src/there as a single item. How can I "expand" the files argument into multiple files to copy?

On a whim I tried specifying the files arg multiple times: docker build --build-arg files='src/hi' --build-arg files='src/there' some_path, but this only copies "there".


Solution

  • I have run into this again years later but now found an adequate solution, assuming the files can be grouped into a fixed set of categories.

    The answer is basically combining the answers of Docker COPY files using glob pattern? and https://unix.stackexchange.com/questions/59112/preserve-directory-structure-when-moving-files-using-find

    Conceptually, the idea is to separate the groups of files in one stage, then copy each group one by one (or ignoring it).

    In code:

    # Create dummy stage for splitting up files
    FROM ubuntu AS src
    RUN mkdir /groups
    WORKDIR /groups
    RUN mkdir group1 group2
    # Makes `group2` the de-facto default, can be any though
    COPY src group2
    RUN rsync --recursive --remove-source-files --prune-empty-dirs \
        --include='hi' \
        --include='there' \
        --exclude='*' \
        group2/ group1/
    
    # Create the image we actually care about
    FROM ubuntu
    COPY --from=src /groups/group1 test/
    RUN commands requiring only `group1` files
    COPY --from=src /groups/group2 test/
    RUN commands requiring all files