web-dev-qa-db-fra.com

COPY / ADD conditionnel dans Dockerfile?

Dans mon Dockerfiles, je souhaiterais copier un fichier dans mon image, s'il existe. Le fichier Requirements.txt pour pip semble être un bon candidat, mais comment cela peut-il être réalisé?

COPY (requirements.txt if test -e requirements.txt; fi) /destination
...
RUN  if test -e requirements.txt; then pip install -r requirements.txt; fi

ou

if test -e requirements.txt; then
    COPY requiements.txt /destination;
fi
RUN  if test -e requirements.txt; then pip install -r requirements.txt; fi
74
derrend

Ce n'est pas actuellement supporté (car je suppose que cela conduirait à une image non reproductible, car le même fichier Dockerfile copierait ou non le fichier, selon son existence).

Ceci est toujours demandé, dans numéro 13045 , en utilisant des caractères génériques: "COPY foo/* bar/" not work if no file in foo "(Mai 2015).
Il ne sera pas implémenté pour le moment (juillet 2015) dans Docker, mais un autre outil de construction tel que bocker pourrait supporter cela.

18
VonC

Voici une solution de contournement simple:

COPY foo file-which-may-exist* /target

Assurez-vous que foo existe, car COPY a besoin d'au moins une source valide.

Si file-which-may-exist est présent, il sera également copié.

REMARQUE: Veillez à ce que votre caractère générique ne récupère pas d'autres fichiers que vous n'avez pas l'intention de copier. Pour faire plus attention, vous pouvez utiliser file-which-may-exist? au lieu (? ne correspond qu’à un seul caractère).

Ou encore mieux, utilisez une classe de caractères telle que celle-ci pour vous assurer que seul un fichier peut correspondre:

COPY foo file-which-may-exis[t] /target
56
jdhildeb

Comme indiqué par ce commentaire , la réponse de Santhosh Hirekerur copie toujours le fichier. Pour archiver une véritable copie conditionnelle, vous pouvez utiliser cette méthode.

ARG BUILD_ENV=copy

FROM Alpine as build_copy
ONBUILD COPY file /file

FROM Alpine as build_no_copy
ONBUILD RUN echo "I don't copy"

FROM build_${BUILD_ENV}
# other stuff

Les instructions ONBUILD garantissent que le fichier n'est copié que si la "branche" est sélectionnée par le BUILD_ENV. Définissez cette var en utilisant un petit script avant d'appeler docker build

9
Siyu

Solution de contournement

J'avais l'exigence sur la copie du dossier sur le serveur basé sur les variables ENV. J'ai pris l'image du serveur vide. créé la structure requise du dossier de déploiement dans le dossier local. puis ajouté sous la ligne à DockerFile copier le dossier dans le conteneur. I n dernier point d’entrée ajouté pour exécuter init file.sh avant que le menu fixe ne démarre le serveur.

#below lines added to integrate testing framework
RUN mkdir /mnt/conf_folder
ADD install /mnt/conf_folder/install
ADD install_test /mnt/conf_folder/install_test
ADD custom-init.sh /usr/local/bin/custom-init.sh
ENTRYPOINT ["/usr/local/bin/custom-init.sh"]

Ensuite, créez le fichier custom-init.sh en local avec un script comme ci-dessous

#!/bin/bash
if [ "${BUILD_EVN}" = "TEST" ]; then
    cp -avr /mnt/conf_folder/install_test/* /mnt/wso2das-3.1.0/
else
    cp -avr /mnt/conf_folder/install/* /mnt/wso2das-3.1.0/
fi;

Dans docker-compose fichier sous les lignes.

environnement: - BUILD_EVN = TEST

Ces modifications copient le dossier dans le conteneur lors de la génération du menu fixe. Lorsque nous exécutons docker-compos up, il copie ou déploie le dossier réellement requis sur le serveur avant le démarrage du serveur.

6
Santhosh Hirekerur

Copiez tous les fichiers dans un répertoire jetable, sélectionnez celui que vous voulez et laissez le reste.

COPY . /throwaway
RUN cp /throwaway/requirements.txt . || echo 'requirements.txt does not exist'
RUN rm -rf /throwaway

Vous pouvez obtenir quelque chose de similaire en utilisant les étapes de construction, qui reposent sur la même solution, en utilisant cp pour copier sous condition. En utilisant une étape de construction, votre image finale n'inclura pas tout le contenu de la valeur initiale COPY.

FROM Alpine as copy_stage
COPY . .
RUN mkdir /dir_for_maybe_requirements_file
RUN cp requirements.txt /dir_for_maybe_requirements_file &>- || true

FROM Alpine
# Must copy a file which exists, so copy a directory with maybe one file
COPY --from=copy_stage /dir_for_maybe_requirements_file /
RUN cp /dir_for_maybe_requirements_file/* . &>- || true
CMD sh
1
cdosborn