Docker COPY files using glob pattern?
There is a solution based on multistage-build feature:
FROM node:12.18.2-alpine3.11WORKDIR /appCOPY ["package.json", "yarn.lock", "./"]# Step 2: Copy whole appCOPY packages packages# Step 3: Find and remove non-package.json filesRUN find packages \! -name "package.json" -mindepth 2 -maxdepth 2 -print | xargs rm -rf# Step 4: Define second build stageFROM node:12.18.2-alpine3.11WORKDIR /app# Step 5: Copy files from the first build stage.COPY --from=0 /app .RUN yarn install --frozen-lockfileCOPY . .# To restore workspaces symlinksRUN yarn install --frozen-lockfileCMD yarn start
On Step 5
the layer cache will be reused even if any file in packages
directory has changed.
To follow-up @FezVrasta's comment to my first answer, if you can't possibly enumerate all the subdirectories at stake in the Dockerfile, but want to copy all the files in two steps to take advantage of Docker cache capabilities, you could try the following workaround:
- Devise a wrapper script (say, in bash) that copies the required
package.json
files to a separate directory (say,.deps/
) built with a similar hierarchy, then calldocker build …
- Adapt the Dockerfile to copy (and rename) the separate directory beforehand, and then call
yarn install --pure-lockfile
…
All things put together, this could lead to the following files:
### ./build.bash ####!/bin/bashtag=copy-example:latestrm -f -r .deps # optional, to be sure that there is# no extraneous "package.json" from a previous buildfind . -type d \( -path \*/.deps \) -prune -o \ -type f \( -name "package.json" \) \ -exec bash -c 'dest=".deps/$1" && \ mkdir -p -- "$(dirname "$dest")" && \ cp -av -- "$1" "$dest"' bash '{}' \;# instead of mkdir + cp, you may also want to use# rsync if it is available in your environment...sudo docker build -t "$tag" .
and
### ./Dockerfile ###FROM ...WORKDIR /usr/src/app# COPY package.json . # subsumed by the following commandCOPY .deps .# and not "COPY .deps .deps", to avoid doing an extra "mv"COPY yarn.lock .RUN yarn install --pure-lockfileCOPY . .# Notice that "COPY . ." will also copy the ".deps" folder; this is# maybe a minor issue, but it could be avoided by passing more explicit# paths than just "." (or by adapting the Dockerfile and the script and# putting them in the parent folder of the Yarn application itself...)
As mentioned in the official Dockerfile reference for COPY <src> <dest>
The COPY instruction copies new files or directories from
<src>
and adds them to the filesystem of the container at the path<dest>
.
For your case
Each may contain wildcards and matching will be done using Go’s
filepath.Match
rules.
These are the rules. They contain this:
'*' matches any sequence of non-Separator characters
So try to use *
instead of **
in your pattern.