Un conteneur Docker dans un conteneur Docker utilise le démon Docker de l'hôte parent et, par conséquent, tous les volumes montés dans le cas "docker-in-docker" sont toujours référencés à partir de l'hôte et non du conteneur.
Par conséquent, le chemin réel monté à partir du conteneur Jenkins "n'existe pas" dans HOST. De ce fait, un nouveau répertoire est créé dans le conteneur "docker-in-docker" qui est vide. La même chose s'applique lorsqu'un répertoire est monté sur un nouveau conteneur Docker à l'intérieur d'un conteneur.
Chose très basique et évidente que j'ai manquée, mais réalisée dès que j'ai tapé la question.
Une autre façon de procéder consiste à utiliser des volumes nommés ou des conteneurs de volumes de données. De cette façon, le conteneur à l'intérieur n'a rien à savoir sur l'hôte et le conteneur Jenkins et le conteneur de construction référencent le volume de données de la même manière.
J'ai essayé de faire quelque chose de similaire à ce que vous faites, sauf avec un agent plutôt qu'en utilisant le maître Jenkins. Le problème était le même dans la mesure où je ne pouvais pas monter l'espace de travail Jenkins dans le conteneur intérieur. Ce qui a fonctionné pour moi était d'utiliser l'approche du conteneur de volume de données et les fichiers de l'espace de travail étaient visibles à la fois pour le conteneur d'agent et le conteneur interne. Ce que j'ai aimé dans cette approche, c'est que les deux conteneurs référencent le volume de données de la même manière. Monter des répertoires avec un conteneur interne serait délicat car le conteneur interne doit maintenant savoir quelque chose sur l'hôte sur lequel son conteneur parent s'exécute.
J'ai un article de blog détaillé sur mon approche ici :
http://damnhandy.com/2016/03/06/creating-containerized-build-environments-with-the-jenkins-pipeline-plugin-and-docker-well-almost/
Ainsi que le code ici :
https://github.com/damnhandy/jenkins-pipeline-docker
Dans mon cas spécifique, tout ne fonctionne pas comme je le souhaiterais en termes de plugin Jenkins Pipeline. Mais cela résout le problème de la capacité du conteneur interne à accéder au répertoire de l'espace de travail Jenkins.
Beaucoup de bonnes informations dans ces messages, mais je trouve qu'aucun d'entre eux n'est très clair sur le conteneur auquel il fait référence. Labellisons donc les 3 environnements :
- hébergeur :H
- conteneur docker fonctionnant sur H : D
- conteneur docker fonctionnant en D :D2
Nous savons tous comment monter un dossier de H vers D :commencez D par
docker run ... -v <path-on-H>:<path-on-D> -v /var/run/docker.sock:/var/run/docker.sock ...
Le défi est :vous voulez path-on-H
être disponible en D2 en tant que path-on-D2
.
Mais on s'est tous fait mordre en essayant de monter le même path-on-H
en D2, car nous avons commencé D2 avec
docker run ... -v <path-on-D>:<path-on-D2> ...
Lorsque vous partagez le socket docker sur H avec D, l'exécution des commandes docker dans D les exécute essentiellement sur H. En effet, si vous démarrez D2 comme ceci, tout fonctionne (de manière assez inattendue au début, mais cela a du sens quand on y pense):
docker run ... -v <path-on-H>:<path-on-D2> ...
Le problème suivant est que pour beaucoup d'entre nous, path-on-H
changera selon qui le dirige. Il existe de nombreuses façons de transmettre des données à D afin qu'il sache quoi utiliser pour path-on-H
, mais probablement le plus simple est une variable d'environnement. Pour clarifier le but d'une telle var, je commence son nom par DIND_
. Puis de H commencer D comme ceci :
docker run ... -v <path-on-H>:<path-on-D> --env DIND_USER_HOME=$HOME \
--env DIND_SOMETHING=blabla -v /var/run/docker.sock:/var/run/docker.sock ...
et de D commencez D2 comme ceci :
docker run ... -v $DIND_USER_HOME:<path-on-D2> ...