2015-07-13 4 views
14

Ich verwende einen Jenkins-Cluster, in dem Master und Slave beide als Docker-Container ausgeführt werden.Docker in Docker kann das Volume nicht mounten

Der Host ist die neueste boot2docker VM, die auf MacOS ausgeführt wird.

Damit Jenkins der Lage sein Einsatz auszuführen Docker verwenden, habe ich den docker.sock und Docker-Client von dem Host zu dem Jenkins-Container wie folgt montiert: -

docker run -v /var/run/docker.sock:/var/run/docker.sock -v $(which docker):/usr/bin/docker -v $HOST_JENKINS_DATA_DIRECTORY/jenkins_data:/var/jenkins_home -v $HOST_SSH_KEYS_DIRECTORY/.ssh/:/var/jenkins_home/.ssh/ -p 8080:8080 jenkins 

ich Fragen stehe vor bei der Montage ein Volume für Docker-Container, die im Jenkins-Container ausgeführt werden. Zum Beispiel, wenn ich einen anderen Container in der Jenkins Container ausgeführt werden müssen, ich folgendes: -

sudo docker run -v $JENKINS_CONTAINER/deploy.json:/root/deploy.json $CONTAINER_REPO/$CONTAINER_IMAGE 

Die oben den Behälter läuft, aber die Datei „deploy.json“ wird nicht als Datei montiert, aber stattdessen als "Verzeichnis". Selbst wenn ich ein Verzeichnis als Volume mounte, kann ich die Dateien im resultierenden Container nicht anzeigen.

Ist dies ein Problem, wegen Dateiberechtigungen wegen Docker in Docker Fall?

Alle Zeiger wären nützlich!

Danke!

Antwort

27

Ein Docker-Container in einem Docker-Container verwendet den Docker-Daemon des Parent HOST und daher werden alle Volumes, die im Fall "Docker-in-docker" eingehängt werden, immer noch vom HOST und nicht vom Container referenziert.

Daher der tatsächliche Pfad, der von dem Jenkins-Container bereitgestellt wird, "existiert nicht" in dem HOST. Aus diesem Grund wird ein neues Verzeichnis im Container "docker-in-docker" erstellt, der leer ist. Dasselbe gilt, wenn ein Verzeichnis in einem neuen Docker-Container in einem Container bereitgestellt wird.

Sehr einfache und offensichtliche Sache, die ich verpasste, aber realisiert, sobald ich die Frage eintippte.

+0

Danke. Sehr hilfreich. Definitiv nicht bemerkt, dass es sich so verhalten würde. –

+0

Gut zu wissen, dass es hilfreich war. Vielen Dank! – ZephyrPLUSPLUS

+7

Also, was ist die Lösung? Da docker Dokumentation bezieht sich auf https://jpetazzo.github.io/2015/09/03/do-not-use-docker-in-docker-for-ci/ was besagt, Docker auf diese Weise zu verwenden. Auf diese Weise können jedoch keine Volumes von einem Andockcontainer zu einem anderen bereitgestellt werden. Datenvolumen? –

2

Eine andere Möglichkeit besteht darin, entweder benannte Volumes oder Datenvolumencontainer zu verwenden. Auf diese Weise muss der Container im Inneren nichts über den Host wissen, und sowohl der Jenkins-Container als auch der Erstellungscontainer verweisen auf dieselbe Weise auf das Datenvolumen.

Ich habe versucht, etwas ähnliches zu tun, was Sie tun, außer mit einem Agenten, anstatt mit dem Jenkins-Master. Das Problem war das gleiche, weil ich den Jenkins-Arbeitsbereich im inneren Container nicht montieren konnte. Was für mich funktionierte, war die Verwendung des Datenvolumen-Container-Ansatzes, und die Arbeitsbereichsdateien waren für den Agentencontainer und den inneren Container sichtbar. Was mir am Ansatz gefallen hat, ist, dass die beiden Container das Datenvolumen auf die gleiche Weise referenzieren. Das Mounten von Verzeichnissen mit einem inneren Container wäre schwierig, da der innere Container jetzt etwas über den Host wissen muss, auf dem der übergeordnete Container ausgeführt wird.

Ich habe detaillierte Blog-Post über meinen Ansatz hier:

http://damnhandy.com/2016/03/06/creating-containerized-build-environments-with-the-jenkins-pipeline-plugin-and-docker-well-almost/

Neben Code hier:

https://github.com/damnhandy/jenkins-pipeline-docker

In meinem speziellen Fall nicht alles funktioniert so, wie ich würde es in Bezug auf die Jenkins-Pipeline-Plugin.Es behandelt jedoch das Problem, dass der innere Container auf das Jenkins-Arbeitsbereichsverzeichnis zugreifen kann.

+0

Ich kann nicht glauben, dass jemand diese Antwort abgelehnt hat. Das ist brilliant und kommt direkt auf den Punkt. Es ist eine Lösung, die das Gefühl hat, dass sie die Docker-Funktionen aus den Gründen nutzt, aus denen sie bestehen. – neverfox

+0

Ein weiterer damit in Verbindung stehender Blogeintrag kann gefunden werden [hier] (https://www.develves.net/blogs/asd/2016-05-27-alternative-to-docker-in-docker/) (nicht meins). – helmesjo

4

In Bezug auf Ihren Anwendungsfall Jenkins bezogen, können Sie einfach fälscht der Weg durch einen Symlink auf dem Host erstellen:

ln -s $HOST_JENKINS_DATA_DIRECTORY/jenkins_data /var/jenkins_home 
+0

Ich löste mein Problem Danke! –

0

Ein Weg, um dieses Problem zu arbeiten, ist ein Verzeichnis zu montieren (in Ihrem Docker Behälter in dem Sie Ihren Docker-Socket gemountet haben) mit dem exakt gleichen Pfad für das Ziel. Wenn Sie dann einen Container innerhalb dieses Containers ausführen, können Sie alles innerhalb des Pfades dieses Mount in den neuen Container laden, indem Sie docker -v verwenden.

Nehmen Sie dieses Beispiel:

# Spin up your container from which you will use docker 
docker run -v /some/dir:/some/dir -v /var/run/docker.sock:/var/run.docker.sock docker:latest 

# Now spin up a container from within this container 
docker run -v /some/dir:/usr/src/app $CONTAINER_IMAGE 

Der Ordner /some/dir wird nun in Ihrem Host montiert ist, der Zwischenbehälter sowie Ihre Zielbehälter. Da der Pfad des Mount auf dem Host als "fast docker-in-docker" -Container vorhanden ist, können Sie docker -v wie erwartet verwenden.

Es ähnelt dem Vorschlag, einen Symlink auf dem Host zu erstellen, aber ich fand dies (zumindest in meinem Fall) eine sauberere Lösung. Vergiss nicht, danach das Verzeichnis auf dem Host zu säubern! ;)