Comment puis-je inclure des fichiers en dehors du contexte de construction de Docker en utilisant la commande "ADD" dans le fichier Docker?
Dans la documentation Docker:
Le chemin doit être à l'intérieur du contexte de la construction; vous ne pouvez pas ADD ../something/something, car la première étape d'une génération de docker consiste à envoyer le répertoire de contexte (et ses sous-répertoires) au démon de docker.
Je ne veux pas restructurer tout mon projet juste pour accueillir Docker dans cette affaire. Je souhaite conserver tous mes fichiers Docker dans le même sous-répertoire.
En outre, il semble que Docker ne prend pas encore (et peut-être jamais) en charge les liens symboliques: la commande Dockerfile ADD 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 génération Docker (et configurer mon contrôle de version pour ignorer ces fichiers). Existe-t-il une meilleure solution de contournement que cela?
FROM
de continuer à partir de là. Je ne changerais pas la structure du projet pour accueillir Docker (ou tout autre outil de construction).Réponses:
La meilleure façon de contourner ce problème est de spécifier le Dockerfile indépendamment du contexte de génération, en utilisant -f.
Par exemple, cette commande donnera à la commande ADD accès à tout ce qui se trouve dans votre répertoire actuel.
Mise à jour : Docker permet désormais d'avoir le Dockerfile en dehors du contexte de construction (corrigé dans 18.03.0-ce, https://github.com/docker/cli/pull/886 ). Vous pouvez donc aussi faire quelque chose comme
la source
dockerfile:
propriété dans labuild:
section du fichier Compose docs.docker.com/compose/compose-file/#/compose-file-referenceADD
un fichier qui est en dehors du répertoire de contexte? C'est ce que j'essaie de faire, mais je ne pense pas que l'utilisation-f
de fichiers externes puisse être ajoutée.build: context: .., dockerfile: dir/Dockerfile
. Maintenant, mon contexte de construction est le répertoire parent!Je me retrouve souvent à utiliser l'
--build-arg
option à cette fin. Par exemple, après avoir mis ce qui suit dans le Dockerfile:Vous pouvez simplement faire:
Mais notez l'avertissement suivant de la documentation Docker :
Avertissement: Il n'est pas recommandé d'utiliser des variables au moment de la construction pour transmettre des secrets comme les clés github, les informations d'identification de l'utilisateur, etc. Les valeurs des variables au moment de la construction sont visibles par tout utilisateur de l'image avec la commande docker history.
la source
Sous Linux, vous pouvez monter d'autres répertoires au lieu de les créer des liens symboliques
Voir /superuser/842642 pour plus de détails.
Je ne sais pas si quelque chose de similaire est disponible pour d'autres systèmes d'exploitation. J'ai également essayé d'utiliser Samba pour partager un dossier et le remonter dans le contexte Docker qui fonctionnait également.
la source
J'ai passé un bon moment à essayer de trouver un bon modèle et à mieux expliquer ce qui se passe avec cette prise en charge des fonctionnalités. J'ai réalisé que la meilleure façon de l'expliquer était la suivante ...
Donc, cela dit, voici un exemple du Dockerfile qui doit réutiliser un fichier appelé
start.sh
Dockerfile
Il
ALWAYS
se chargera à partir de son chemin d'accès relatif, ayant le répertoire courant de lui-même commelocal
référence aux chemins que vous spécifiez.Des dossiers
Compte tenu de cette idée, nous pouvons penser à avoir plusieurs copies pour les Dockerfiles construisant des choses spécifiques, mais ils ont tous besoin d'accéder à
start.sh
.Compte tenu de cette structure et des fichiers ci-dessus, voici un docker-compose.yml
docker-compose.yaml
shared
répertoire de contexte est leruntime
répertoire.context
.dockerfile
.Le
docker-compose.yml
est comme suitall-service
est défini comme contexte, le fichier partagé ystart.sh
est copié ainsi que le Dockerfile spécifié par chaquedockerfile
.À votre santé!
la source
a/b/c
, alors oui en cours d' exécutiondocker build .
enc
ne vous permettra pas d'accéder../file-in-b
. Mais, je pense que le malentendu général dans ce (ou du moins le mien l'était) est que le contexte est défini par l'emplacement indiqué par le premier argument de la commande build, et non par l'emplacement du Dockerfile. Donc, comme indiqué dans la réponse acceptée: dea
:docker build -f a/b/c/Dockerfile .
signifie que dans le Dockerfile.
est maintenant le dossiera
Si vous lisez la discussion du numéro 2745, non seulement Docker peut ne jamais prendre en charge les liens symboliques, mais également ne jamais prendre en charge l'ajout de fichiers en dehors de votre contexte. Semble être une philosophie de conception selon laquelle les fichiers qui entrent dans la construction de docker devraient explicitement faire partie de son contexte ou provenir d'une URL où il est vraisemblablement déployé aussi avec une version fixe afin que la construction soit reproductible avec des URL bien connues ou des fichiers livrés avec le conteneur de docker.
Juste mon avis mais je pense que vous devriez restructurer pour séparer le code et les référentiels docker. De cette façon, les conteneurs peuvent être génériques et extraire n'importe quelle version du code au moment de l'exécution plutôt qu'au moment de la génération.
Sinon, utilisez docker comme artefact de déploiement de code fondamental, puis placez le fichier docker à la racine du référentiel de code. si vous suivez cette route, il est probablement judicieux d'avoir un conteneur Docker parent pour des détails plus généraux sur le niveau du système et un conteneur enfant pour une configuration spécifique à votre code.
la source
Je pense que la solution de contournement la plus simple serait de changer le «contexte» lui-même.
Ainsi, par exemple, au lieu de donner:
qui définit le répertoire courant comme contexte, disons que vous vouliez le répertoire parent comme contexte, utilisez simplement:
la source
make build
et il extrait tous les fichiers nécessaires s'ils ont été mis à jour, puis il appelle la construction de docker appropriée ... J'ai besoin de faire un travail supplémentaire, mais cela fonctionne parfaitement parce que je suis en plein contrôle.Vous pouvez également créer un tarball de ce dont l'image a besoin en premier et l'utiliser comme contexte.
https://docs.docker.com/engine/reference/commandline/build/#/tarball-contexts
la source
tar zc /dir1 /dir2 |docker build -
. Cela a été très utile dans mon cas.En utilisant docker-compose, j'ai accompli 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 me fie à l'image précédemment validée, qui contient toutes les données stockées aux 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
docker commit
commandela source
J'ai eu ce même problème avec un projet et certains fichiers de données que je n'ai pas pu déplacer dans le contexte du référentiel pour des raisons HIPPA. J'ai fini par utiliser 2 Dockerfiles. On construit l'application principale sans les éléments dont j'avais besoin en dehors du conteneur et les publie sur le référentiel interne. Ensuite, un deuxième dockerfile extrait cette image et ajoute les données et crée une nouvelle image qui est ensuite déployée et jamais stockée nulle part. Pas idéal, mais cela a fonctionné à mes fins de garder les informations sensibles hors du référentiel.
la source
Une solution de contournement simple pourrait être de simplement monter le volume (en utilisant l'indicateur -v ou --mount) sur le conteneur lorsque vous l'exécutez et d'accéder aux fichiers de cette façon.
exemple:
pour plus d'informations, voir: https://docs.docker.com/storage/volumes/
la source
docker run
est trop tard.Comme cela est décrit dans ce problème GitHub, la génération se produit réellement
/tmp/docker-12345
, donc un chemin relatif comme../relative-add/some-file
est relatif à/tmp/docker-12345
. Il rechercherait ainsi/tmp/relative-add/some-file
, ce qui est également indiqué dans le message d'erreur. *Il n'est pas autorisé d'inclure des fichiers en dehors du répertoire de génération, ce qui entraîne le message "Chemin d'accès interdit". "
la source
Une façon simple et rapide consiste à définir le contexte de génération sur autant de niveaux que nécessaire, mais cela peut avoir des conséquences. Si vous travaillez dans une architecture de microservices qui ressemble à ceci:
Vous pouvez définir le contexte de génération sur le parent
Code
répertoire , puis accéder à tout, mais il s'avère qu'avec un grand nombre de référentiels, cela peut entraîner une longue durée de génération.Un exemple de situation pourrait être qu'une autre équipe gère un schéma de base de données dans
Repo1
et le code de votre équipe dansRepo2
dépend. Vous voulez ancrer cette dépendance avec certaines de vos propres données de départ sans vous soucier des changements de schéma ou polluer le référentiel de l'autre équipe (selon les changements, vous devrez peut-être toujours changer vos scripts de données de départ bien sûr) La deuxième approche est hacky mais contourne la question des versions longues:Créez un script sh (ou ps1)
./Code/Repo2
pour copier les fichiers dont vous avez besoin et appelez les commandes docker de votre choix, par exemple:Dans le fichier docker-compose, définissez simplement le contexte en tant que
Repo2
root et utilisez le contenu du./db/schema
répertoire dans votre dockerfile sans vous soucier du chemin. Gardez à l'esprit que vous courrez le risque de commettre accidentellement ce répertoire dans le contrôle de code source, mais les actions de nettoyage de script devraient être assez faciles.la source
Dans mon cas, mon Dockerfile est écrit comme un modèle contenant des espaces réservés que je remplace par une valeur réelle en utilisant mon fichier de configuration.
Je ne pouvais donc pas spécifier ce fichier directement mais le canaliser dans la construction du docker comme ceci:
Mais à cause du tuyau, la
COPY
commande n'a pas fonctionné. Mais la manière ci-dessus le résout par-f -
(en disant explicitement que le fichier n'est pas fourni). Ne faire que-
sans l'-f
indicateur, le contexte ET le Dockerfile ne sont pas fournis, ce qui est une mise en garde.la source
L'astuce consiste à reconnaître que vous pouvez spécifier le contexte dans la commande de génération pour inclure les fichiers du répertoire parent si vous spécifiez le chemin Docker, je changerais mon Dockerfile pour qu'il ressemble à ceci:
Ensuite, ma commande de construction peut ressembler à ceci:
Depuis le répertoire du projet
Du projet / docker
la source