J'ai un monorepo géré par Yarn. J'aimerais tirer parti des couches de cache de Docker pour accélérer mes constructions. Pour ce faire, j'aimerais d'abord copier les fichiers package.json
et yarn.lock
, exécuter yarn install
, puis copier le reste les fichiers.
Ceci est ma structure de repo:
packages/one/package.json
packages/one/index.js
packages/two/package.json
packages/two/index.js
package.json
yarn.lock
Et voici la partie intéressée du fichier Dockerfile:
COPY package.json .
COPY yarn.lock .
COPY packages/**/package.json ./
RUN yarn install --pure-lockfile
COPY . .
Le problème est que la 3ème commande COPY
ne copie rien, comment puis-je obtenir le résultat attendu?
Comme mentionné dans référence officielle de Dockerfile pour COPY <src> <dest>
L'instruction COPY copie les nouveaux fichiers ou répertoires à partir de
<src>
et les ajoute au système de fichiers du conteneur à l'emplacement<dest>
.
Pour votre cas
Chacune peut contenir des caractères génériques et la correspondance sera effectuée à l’aide des règles
filepath.Match
de Go.
C'est les règles . Ils contiennent ceci:
'*' correspond à n'importe quelle séquence de caractères non séparateurs
Essayez donc d'utiliser *
au lieu de **
dans votre modèle.
Pour faire suite au commentaire de @ FezVrasta sur mon première réponse , si vous ne pouvez pas énumérer tous les sous-répertoires en jeu dans le fichier Docker, mais souhaitez copier tous les fichiers en deux étapes pour tirer parti des capacités de la mémoire cache Docker, vous pouvez essayer la solution suivante:
package.json
requis dans un répertoire distinct (par exemple, .deps/
) créé avec une hiérarchie similaire, puis appelez docker build …
yarn install --pure-lockfile
…Toutes choses réunies, cela pourrait conduire aux fichiers suivants:
### ./build.bash ###
#!/bin/bash
tag=copy-example:latest
rm -f -r .deps # optional, to be sure that there is
# no extraneous "package.json" from a previous build
find . -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" .
et
### ./Dockerfile ###
FROM ...
WORKDIR /usr/src/app
# COPY package.json . # subsumed by the following command
COPY .deps .
# and not "COPY .deps .deps", to avoid doing an extra "mv"
COPY yarn.lock .
RUN yarn install --pure-lockfile
COPY . .
# 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...)
Comme indiqué dans mon commentaire ci-dessus, l'utilisation de la directive COPY
avec un glob pour spécifier plusieurs sous-dossiers contenant un fichier portant le même nom ne fonctionnera pas; mais une solution simple consisterait à coder en dur le chemin de vos sous-dossiers en écrivant quelque chose comme ceci:
# ...
WORKDIR /usr/src/app
COPY package.json .
COPY yarn.lock .
COPY packages/one/package.json packages/one/
COPY packages/two/package.json packages/two/
RUN yarn install --pure-lockfile
COPY . .
# ...
et je me souviens que la directive COPY
se charge de créer les dossiers de destination (c.-à-d., no need to RUN mkdir -p packages/one
or so)