COPIE avec docker mais avec exclusion

231

Dans un Dockerfile, j'ai

COPY . .

Je veux exclure un répertoire entier, dans mon cas, le répertoire node_modules.

Quelque chose comme ça:

   COPY [all but **/node_modules/**] .

Est-ce possible avec Docker?

Alexander Mills
la source
23
Et alors .dockerignore?
Anthony Sottile
Je cherche une réponse à cette question connexe: stackoverflow.com/questions/50547489/…
Alexander Mills

Réponses:

377

Créez un fichier .dockerignoredans votre répertoire de contexte de construction de docker (donc dans ce cas, très probablement un répertoire parent de node_modules) avec une ligne dedans:

**/node_modules

bien que vous souhaitiez probablement:

node_modules

Informations sur dockerignore: https://docs.docker.com/engine/reference/builder/#dockerignore-file

avec
la source
5
merci, donc la "COPIE." la commande n'a pas besoin de changer, je suppose
Alexander Mills
Pas vraiment: /config/nginx/ /config/logstash/je trouve ça dans le container bash:ls config/ gunicorn logs logstash nginx
SalahAdDin
3
@SalahAdDin pour la même raison que vous n'avez pas écrit ls /config/, avez-vous essayé d'ajouter ces chemins à votre .dockerignore sans le premier /?
Pablo
8
Ne node_modulesfonctionne tout simplement pas dans les sous-répertoires.
rustyx
5
Cela ne résout pas vraiment le problème si vous voulez l'avoir copié mais tout simplement pas dans cette couche ...
Wes
33

Pour ceux qui ne peuvent pas utiliser un fichier .dockerignore (par exemple, si vous avez besoin du fichier dans une COPIE mais pas dans une autre):

Oui, mais vous avez besoin de plusieurs instructions COPY. Plus précisément, vous avez besoin d'une COPIE pour chaque lettre du nom de fichier que vous souhaitez exclure.

COPY [^n]*    # All files that don't start with 'n'
COPY n[^o]*   # All files that start with 'n', but not 'no'
COPY no[^d]*  # All files that start with 'no', but not 'nod'

Continuez jusqu'à ce que vous ayez le nom de fichier complet, ou juste le préfixe dont vous êtes raisonnablement sûr qu'il n'aura pas d'autres fichiers.

Alex
la source
1
Cela ne vaudra pas la peine car vous en obtiendrez COPY failed: no source files were specifiedquand il n'y aura pas de fichiers commençant par «non», mais pas par «hochement de tête».
mheck
1
Sinon, vous pouvez utiliser deux sous-répertoires différents (pour différentes cibles de copie), de sorte que par exemple dans ma configuration nginx, je l' aurais src/ira /var/wwwet /conf/nginx.confaller /etc/nginx/conf.d/default.conf. De plus, vous pouvez tout copier, et RUN rm -r confplus tard (aussi garder l'arborescence source telle qu'elle était). J'aimerais savoir si quelqu'un a une autre suggestion.
Yuval
1
Quelle serait une solution pour des types de fichiers ou des fins de fichier spécifiques si je le faisais comme ça?
Lea Reimann
Le seul inconvénient de cette approche est que votre structure de dossiers est aplatie
Islam Q.
Si vous n'avez que quelques répertoires à copier (dites seulement '/ app' ou '/ src'). Un moyen plus simple serait de copier les répertoires individuellement (pour conserver leur structure) et vous n'en aurez alors besoin que d'un COPY [^node_modules]*pour copier tous les fichiers de niveau supérieur.
smdufb
9

Dans mon cas, mon Dockerfile contenait une étape d'installation, qui produisait le vendorrépertoire (l'équivalent PHP de node_modules). J'ai ensuite COPYce répertoire sur l'image de l'application finale. Par conséquent, je ne pouvais pas mettre vendordans mon .dockerignore. Ma solution consistait simplement à supprimer le répertoire avant d'effectuer composer install(l'équivalent PHP de npm install).

FROM composer AS composer
WORKDIR /app
COPY . .
RUN rm -rf vendor \
    && composer install 

FROM richarvey/nginx-php-fpm
WORKDIR /var/www/html
COPY --from=composer /app .

Cette solution fonctionne et ne gonfle pas l'image finale, mais elle n'est pas idéale, car le vendorrépertoire sur l'hôte est copié dans le contexte Docker pendant le processus de génération, ce qui ajoute du temps.

Cameron Hudson
la source
3
Notez bien pourquoi vous devez supprimer composer.lockavant composer install. Sans le fichier de verrouillage, un ensemble différent de dépendances (le dossier du fournisseur) peut être installé lors de la prochaine génération.
Lacek
1
@Lacek: Vous avez raison. J'ai mieux appris depuis que j'ai posté ça.
Cameron Hudson
1
@CameronHudson peut-être mettre à jour votre réponse d'origine avant que les gens ne copient / collent cette mauvaise pratique.
Robin van Baalen
2

L'ajout de .dockerignore fonctionne pour moi. Un point supplémentaire Ceux qui essaient cette solution sur Windows , Windows ne vous laisseront pas créer de fichier .dockerignore (car il ne permet pas par défaut de créer un fichier commençant par.)

Pour créer un tel fichier commençant par. sous Windows , incluez également un point de fin, comme: .dockerignore.et appuyez sur Entrée (à condition que vous ayez activé les options d'extension de vue à partir des options de dossier)

Paras Patidar
la source
6
Vous pouvez créer un fichier dans des fenêtres qui commence par un point en le terminant également par un point.
Jim Pedid
0

Exclusion de node_modules du répertoire actuel

node_modules

Exclusion de node_modules dans tous les sous-répertoires immédiats

*/node_modules

Voici les documents officiels

kta
la source