web-dev-qa-db-fra.com

Comment inclure des fichiers en dehors du contexte de construction de Docker?

Comment puis-je inclure des fichiers en dehors du contexte de construction de Docker à l'aide de la commande "ADD" dans le fichier Docker?

À partir de la documentation Docker:

Le chemin doit être dans le contexte de la construction; vous ne pouvez pas ajouter ../quelque chose/quelque chose, parce que la première étape de la construction d'un menu fixe consiste à envoyez le répertoire contextuel (et les sous-répertoires) au démon docker.

Je ne veux pas restructurer l’ensemble de mon projet uniquement pour tenir compte de Docker dans cette affaire. Je souhaite conserver tous mes fichiers Docker dans le même sous-répertoire.

De plus, il semble que Docker ne supporte pas encore (et ne puisse jamais) prendre en charge les liens symboliques: La commande ADD de Dockerfile ne suit pas les liens symboliques sur l'hôte 1676.

La seule autre chose à laquelle je peux penser est d'inclure une étape de pré-génération pour copier les fichiers dans le contexte de construction de Docker (et configurer mon contrôle de version pour ignorer ces fichiers). Existe-t-il une meilleure solution de contournement pour cela?

240
ben_frankly

La meilleure façon de contourner ce problème consiste à spécifier le fichier Docker indépendamment du contexte de construction, à l'aide de -f.

Par exemple, cette commande donnera à la commande ADD l'accès à tout ce qui se trouve dans votre répertoire actuel.

docker build -f docker-files/Dockerfile .

Update: Docker permet désormais de placer le fichier Docker en dehors du contexte de construction (corrigé dans 18.03.0-ce, https://github.com/docker/cli/pull/886 ). Donc, vous pouvez aussi faire quelque chose comme

docker build -f ../Dockerfile .
234
Cyberwiz

Sous Linux, vous pouvez monter d'autres répertoires au lieu de les rapprocher.

mount --bind olddir newdir

Voir https://superuser.com/questions/842642 pour plus de détails.

Je ne sais pas si quelque chose de similaire est disponible pour les autres systèmes d'exploitation . J'ai également essayé d'utiliser Samba pour partager un dossier et le remonter dans le contexte de Docker qui fonctionnait également.

35
Günter Zöchbauer

Je me retrouve souvent à utiliser l'option --build-arg à cette fin. Par exemple, après avoir ajouté ce qui suit dans le fichier Dockerfile:

ARG SSH_KEY
RUN echo "$SSH_KEY" > /root/.ssh/id_rsa

Vous pouvez juste faire:

docker build -t some-app --build-arg SSH_KEY="$(cat ~/file/outside/build/context/id_rsa)" .

Notez toutefois l’avertissement suivant de la documentation de Docker :

Avertissement: Il est déconseillé d'utiliser des variables de génération pour transmettre des secrets tels que des clés github, des informations d'identification d'utilisateur, etc. Les valeurs de variable de génération sont visibles pour tout utilisateur de l'image à l'aide de la commande historique de menu fixe.

35
user2658308

Si vous lisez la discussion dans numéro 2745 non seulement docker ne peut jamais supporter les liens symboliques, il est possible qu'il ne supporte jamais d'ajouter des fichiers hors de votre contexte. Semble être une philosophie de conception selon laquelle les fichiers qui entrent dans la compilation de docker doivent explicitement faire partie de son contexte ou provenir d’une URL où il est vraisemblablement déployé également avec une version corrigée, de sorte que la construction puisse être répétée avec des URL ou des fichiers bien conteneur docker. 

Je préfère construire à partir d'une version contrôlée de la source - c'est-à-dire docker build -t stuff http://my.git.org/repo - sinon je construis à partir d'un endroit aléatoire avec des fichiers aléatoires.

fondamentalement, non .... - SvenDowideit, Docker Inc

Juste mon avis, mais je pense que vous devriez vous restructurer pour séparer les référentiels de code et de docker. Ainsi, les conteneurs peuvent être génériques et extraire n'importe quelle version du code au moment de l'exécution plutôt que de la génération. 

Vous pouvez également utiliser docker comme artefact de déploiement de code fondamental, puis placer le fichier docker à la racine du référentiel de code. Si vous allez dans cette voie, il est probablement logique d’avoir un conteneur docker parent pour des détails plus généraux au niveau système et un conteneur enfant pour une configuration spécifique à votre code. 

17
Usman Ismail

Je pense que la solution la plus simple serait de changer le "contexte" lui-même. 

Ainsi, par exemple, au lieu de donner:

docker build -t hello-demo-app .

qui définit le répertoire courant comme contexte, supposons que vous vouliez le répertoire parent comme contexte, utilisez simplement:

docker build -t hello-demo-app ..
4
Anshuman Manral

Vous pouvez également créer une archive de ce dont l’image a besoin en premier lieu et l’utiliser comme contexte.

https://docs.docker.com/engine/reference/commandline/build/#/tarball-contexts

1
Laurent Picquet

J'ai eu le même problème avec un projet et des fichiers de données que je n'ai pas pu déplacer dans le contexte du repo pour des raisons HIPPA. J'ai fini par utiliser 2 Dockerfiles. On construit l'application principale sans les éléments dont j'avais besoin à l'extérieur du conteneur et les publie dans le référentiel interne. Ensuite, un deuxième fichier docker extrait cette image, ajoute les données et crée une nouvelle image qui est ensuite déployée et jamais stockée. Pas idéal, mais cela a fonctionné dans le but de garder les informations sensibles en dehors du repo.

0
Annulet Consulting

À l'aide de docker-compos, j'ai réalisé cela en créant un service qui monte les volumes dont j'ai besoin et en validant l'image du conteneur. Ensuite, dans le service suivant, je m'appuie sur l'image précédemment validée, qui contient toutes les données stockées dans des emplacements montés. Vous devrez ensuite copier ces fichiers vers leur destination finale, car les répertoires montés sur l'hôte ne sont pas validés lors de l'exécution d'une commande docker commit.

Vous n'avez pas besoin d'utiliser docker-compose pour accomplir cela, mais cela simplifie un peu la vie.

# docker-compose.yml

version: '3'
  services:
    stage:
      image: Alpine
      volumes:
        - /Host/machine/path:/tmp/container/path
      command: bash -c "cp -r /tmp/container/path /final/container/path"
    setup:
      image: stage
# setup.sh

# Start "stage" service
docker-compose up stage

# Commit changes to an image named "stage"
docker commit $(docker-compose ps -q stage) stage

# Start setup service off of stage image
docker-compose up setup
0
Kris Rivera