web-dev-qa-db-fra.com

Docker COPY fichiers en utilisant le motif glob?

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?

6
Fez Vrasta

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.

2
v.karbovnichy

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:

  • Concevez un script d'emballage (par exemple, en bash) qui copie les fichiers package.json requis dans un répertoire distinct (par exemple, .deps/) créé avec une hiérarchie similaire, puis appelez docker build …
  • Adaptez le fichier Docker pour copier (et renommer) le répertoire séparé au préalable, puis appelez 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...)
2
ErikMD

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)

0
ErikMD