Ein Docker-Container in einem Docker-Container verwendet den Docker-Daemon des übergeordneten HOST, und daher werden alle Volumes, die im „Docker-in-Docker“-Fall gemountet sind, immer noch vom HOST und nicht vom Container referenziert.
Daher „existiert“ der tatsächliche Pfad, der aus dem Jenkins-Container bereitgestellt wird, im HOST nicht. Aus diesem Grund wird im Container „docker-in-docker“ ein neues Verzeichnis erstellt, das leer ist. Das Gleiche gilt, wenn ein Verzeichnis in einem neuen Docker-Container in einem Container gemountet wird.
Sehr grundlegende und offensichtliche Sache, die ich übersehen habe, aber sofort erkannt habe, als ich die Frage eingegeben habe.
Eine andere Möglichkeit besteht darin, entweder benannte Volumes oder Datenvolume-Container zu verwenden. Auf diese Weise muss der Container darin nichts über den Host wissen und sowohl der Jenkins-Container als auch der Build-Container referenzieren das Datenvolumen auf die gleiche Weise.
Ich habe versucht, etwas Ähnliches wie Sie zu tun, außer mit einem Agenten und nicht mit dem Jenkins-Master. Das Problem war das gleiche, da ich den Jenkins-Arbeitsbereich nicht im inneren Container bereitstellen konnte. Was für mich funktioniert hat, war die Verwendung des Data Volume Container-Ansatzes, und die Arbeitsbereichsdateien waren sowohl für den Agentencontainer als auch für den inneren Container sichtbar. Was mir an dem Ansatz gefallen hat, ist, dass beide Container auf die gleiche Weise auf das Datenvolumen verweisen. Das Mounten von Verzeichnissen mit einem inneren Container wäre schwierig, da der innere Container jetzt etwas über den Host wissen muss, auf dem sein übergeordneter Container läuft.
Ich habe hier einen ausführlichen Blogbeitrag über meinen Ansatz:
http://damnhandy.com/2016/03/06/creating-containerized-build-environments-with-the-jenkins-pipeline-plugin-and-docker-well-fast/
Sowie Code hier:
https://github.com/damnhandy/jenkins-pipeline-docker
In meinem speziellen Fall funktioniert in Bezug auf das Jenkins-Pipeline-Plugin nicht alles so, wie ich es gerne hätte. Es wird jedoch das Problem behoben, dass der innere Container auf das Jenkins-Arbeitsbereichsverzeichnis zugreifen kann.
Viele gute Informationen in diesen Beiträgen, aber ich finde, keiner von ihnen ist sehr klar darüber, auf welchen Container sie sich beziehen. Lassen Sie uns also die 3 Umgebungen benennen:
- Host:H
- Docker-Container läuft auf H:D
- Docker-Container läuft in D:D2
Wir alle wissen, wie man einen Ordner von H in D einhängt:Beginnen Sie D mit
docker run ... -v <path-on-H>:<path-on-D> -v /var/run/docker.sock:/var/run/docker.sock ...
Die Herausforderung ist:Sie wollen path-on-H
in D2 als path-on-D2
verfügbar sein .
Aber wir wurden alle gebissen, als wir versuchten, denselben path-on-H
zu montieren in D2, weil wir D2 mit
docker run ... -v <path-on-D>:<path-on-D2> ...
Wenn Sie den Docker-Socket auf H mit D teilen, führt das Ausführen von Docker-Befehlen in D sie im Wesentlichen auf H aus. Wenn Sie D2 so starten, funktioniert tatsächlich alles (zunächst ziemlich unerwartet, aber wenn Sie darüber nachdenken):
docker run ... -v <path-on-H>:<path-on-D2> ...
Der nächste knifflige Punkt ist für viele von uns path-on-H
wird sich ändern, je nachdem, wer es betreibt. Es gibt viele Möglichkeiten, Daten an D zu übergeben, damit es weiß, was es für path-on-H
verwenden soll , aber wahrscheinlich am einfachsten ist eine Umgebungsvariable. Um den Zweck einer solchen Variable klarer zu machen, beginne ich ihren Namen mit DIND_
. Dann von H Beginnen Sie D so:
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 ...
und von D starte D2 so:
docker run ... -v $DIND_USER_HOME:<path-on-D2> ...