So mounten Sie lokale Volumes im Docker-Computer

85

Ich versuche Docker-Maschine mit Docker-Compose zu verwenden. Die Datei docker-compose.yml hat folgende Definitionen:

web:
  build: .
  command: ./run_web.sh
  volumes:
    - .:/app
  ports:
    - "8000:8000"
  links:
    - db:db
    - rabbitmq:rabbit
    - redis:redis

Beim Ausführen läuft docker-compose up -dalles gut, bis versucht wird, den Befehl auszuführen und ein Fehler auftritt:

Container b58e2dfa503b696417c1c3f49e2714086d4e9999bd71915a53502cb6ef43936d kann nicht gestartet werden: [8] Systemfehler: exec: "./run_web.sh": stat ./run_web.sh: Keine solche Datei oder kein solches Verzeichnis

Lokale Volumes werden nicht auf dem Remotecomputer bereitgestellt. Welche Strategie wird empfohlen, um die lokalen Volumes mit dem Code der Webanwendungen bereitzustellen?

jdcaballerov
quelle
Die Struktur des Projekts und docker-compose.yml ähnelt diesem Tutorial syncano.com/…
jdcaballerov
1
Dies sollte in den Docker-Compose-Dokumenten als hilfreicher Hinweis für diejenigen enthalten sein, die möglicherweise anfangen, Compose lokal zu verwenden. Hätte mir Stunden WTF-Momente erspart, um herauszufinden, warum zum Teufel mein Dateipfad falsch war oder nicht gefunden wurde. Nein, ich fühle mich einfach albern.
Timbrown

Antworten:

93

Docker-Maschine stellt das Benutzerverzeichnis automatisch bereit ... Aber manchmal reicht das einfach nicht aus.

Ich weiß nichts über Docker 1.6, aber in 1.8 KÖNNEN Sie Docker-Maschinen einen zusätzlichen Mount hinzufügen

Mountpunkt für virtuelle Maschine hinzufügen (Teil 1)

CLI : (Funktioniert nur bei angehaltener Maschine)

VBoxManage sharedfolder add <machine name/id> --name <mount_name> --hostpath <host_dir> --automount

Ein Beispiel in Windows wäre also

/c/Program\ Files/Oracle/VirtualBox/VBoxManage.exe sharedfolder add default --name e --hostpath 'e:\' --automount

GUI : (erfordert NICHT, dass die Maschine gestoppt wird)

  1. Starten Sie "Oracle VM VirtualBox Manager"
  2. Rechtsklick <machine name>(Standard)
  3. Die Einstellungen...
  4. Geteilte Ordner
  5. Der Ordner + das Symbol rechts (Freigabe hinzufügen)
  6. Ordnerpfad: <host dir>(e :)
  7. Ordnername: <mount name>(e)
  8. Aktivieren Sie "Auto-Mount" und "Make Permanent" (Nur lesen, wenn Sie möchten ...) (Das Auto-Mount ist derzeit irgendwie sinnlos ...)

Montage im boot2docker (Teil 2)

Manuelles Mounten in boot2docker :

  1. Es gibt verschiedene Möglichkeiten, sich anzumelden, "Anzeigen" in "Oracle VM VirtualBox Manager" oder ssh / putty in Docker nach IP-Adresse docker-machine ip defaultusw. zu verwenden.
  2. sudo mkdir -p <local_dir>
  3. sudo mount -t vboxsf -o defaults,uid=`id -u docker`,gid=`id -g docker` <mount_name> <local_dir>

Dies ist jedoch nur gut, bis Sie die Maschine neu starten und dann die Halterung verloren geht ...

Hinzufügen eines Automount zu boot2docker :

Während Sie am Computer angemeldet sind

  1. Bearbeiten / erstellen (als root) /mnt/sda1/var/lib/boot2docker/bootlocal.sh, sda1 kann für Sie anders sein ...
  2. Hinzufügen

    mkdir -p <local_dir>
    mount -t vboxsf -o defaults,uid=`id -u docker`,gid=`id -g docker` <mount_name> <local_dir>
    

Mit diesen Änderungen sollten Sie einen neuen Einhängepunkt haben. Dies ist eine der wenigen Dateien, die beim Booten aufgerufen wurden und dauerhaft sind. Bis es eine bessere Lösung gibt, sollte dies funktionieren.


Alte Methode: Weniger empfohlen , aber als Alternative belassen

  • Bearbeiten (als root) /mnt/sda1/var/lib/boot2docker/profile, sda1 kann für Sie anders sein ...
  • Hinzufügen

    add_mount() {
      if ! grep -q "try_mount_share $1 $2" /etc/rc.d/automount-shares ; then
        echo "try_mount_share $1 $2" >> /etc/rc.d/automount-shares
      fi
    }
    
    add_mount <local dir> <mount name>
    

Als letzten Ausweg können Sie die etwas langwierigere Alternative wählen und einfach das Startabbild ändern.

  • git -c core.autocrlf=false clone https://github.com/boot2docker/boot2docker.git
  • cd boot2docker
  • git -c core.autocrlf=false checkout v1.8.1 #oder Ihre entsprechende Version
  • Bearbeiten rootfs/etc/rc.d/automount-shares
  • Fügen Sie try_mount_share <local_dir> <mount_name>am Ende kurz vor fi eine Zeile hinzu. Beispielsweise

    try_mount_share /e e
    

    Stellen Sie nur sicher, dass Sie nichts einstellen, was das Betriebssystem benötigt, wie / bin usw.

  • docker build -t boot2docker . #Dies wird beim ersten Mal ungefähr eine Stunde dauern :(
  • docker run --rm boot2docker > boot2docker.iso
  • Sichern Sie die alte boot2docker.iso und kopieren Sie Ihre neue an ihrer Stelle in ~ / .docker / machine / machine /

Das funktioniert, es ist nur lang und kompliziert

Docker-Version 1.8.1, Docker-Maschine Version 0.4.0

Andy
quelle
Für alle, die Probleme damit haben, bin ich mir ziemlich sicher, dass ich die lokalen Pfade mit denen in der Docker-Maschine übereinstimmen musste. Auch Docker-Compose schien es zu schaffen, die Volumes zu mounten, während reguläres Docker dies nicht tat - nicht sicher warum.
Spieden
3
Erstellt ein Skript für die hier erwähnte Lösung. Funktioniert mit dem neuesten Docker 1.10 und Docker-Machine 0.6.0 gist.github.com/cristobal/fcb0987871d7e1f7449e
Cristobal
In verschiedenen Ressourcen wird über die Verwendung gesprochen /mnt/sda1/var/lib/boot2docker/profile. Können Sie erklären, warum Sie zur Verwendung gewechselt sind /mnt/sda1/var/lib/boot2docker/bootlocal.sh? Auch das Durchstreichen dieses Textes trägt nicht zur Lesbarkeit Ihrer Antwort bei ;-)
Forage
1
@Forage Point über meine Formatierung genommen :). Ich erinnere mich nicht sofort, warum ich die bootlocal.shMethode nicht mehr vorschlage . Ich kann nur sagen, dass es sauberer aussieht, nur einen Mount-Befehl wie bootlocal.shim Profil zu verwenden, als im Profil. Außerdem glaube ich normalerweise, dass das profileMount mehrmals ausgeführt werden kann und ein Mount nur einmal ausgeführt werden muss, sodass es sinnvoller ist. Aber beide können funktionieren.
Andy
LIEBE ES! Danke dir!
Qorbani
28

Auch auf dieses Problem gestoßen und es sieht so aus, als ob lokale Volumes bei Verwendung der Docker-Maschine nicht gemountet werden. Eine Hack-Lösung ist zu

  1. Holen Sie sich das aktuelle Arbeitsverzeichnis der Docker-Machine-Instanz docker-machine ssh <name> pwd

  2. Verwenden Sie ein Befehlszeilentool, rsyncum Ordner auf das Remote-System zu kopieren

    rsync -avzhe ssh --progress <name_of_folder> username@remote_ip:<result _of_pwd_from_1>.
    

Das Standard-pwd ist / root, also wäre der obige Befehl rsync -avzhe ssh --progress <name_of_folder> username@remote_ip:/root

Hinweis: Sie müssten das Kennwort für das Remote-System angeben. Sie können schnell eine erstellen, indem Sie ssh in das Remote-System einfügen und ein Kennwort erstellen.

  1. Ändern Sie den Volume-Mount-Punkt in Ihrer docker-compose.ymlDatei von .:/appauf/root/<name_of_folder>:/app

  2. Lauf docker-compose up -d

Hinweis: Wenn Änderungen lokal vorgenommen werden, vergessen Sie nicht, sie erneut rsyncauszuführen, um die Änderungen auf das Remote-System zu übertragen.

Es ist nicht perfekt, aber es funktioniert. Ein Problem besteht derzeit unter https://github.com/docker/machine/issues/179

Andere Projekte, die versuchen, dieses Problem zu lösen, sind docker-rsync

gbozee
quelle
rsync muss auf dem Remote-System installiert sein. sh: rsync: nicht gefunden rsync: Verbindung unerwartet geschlossen (0 Bytes bisher empfangen) [Absender] rsync-Fehler: Remote-Befehl nicht gefunden (Code 127) unter / SourceCache / rsync / rsync -45 / rsync / io.c (453) [sender = 2.6.9] `Wie haben Sie es zum Laufen gebracht?
Krinker
1
rsync muss auf Ihrem lokalen System installiert sein
gbozee
Wenn ich diese Schritte verwende, wird mein Digitalocean-Host vollständig gesperrt. Die Dateien werden problemlos übertragen. Wenn ich jedoch versuche, die Verbindung zum Host mit der Docker-Maschine exit status 255wiederherzustellen, muss die Maschine vollständig neu erstellt werden.
Dsifford
1
Erstellt ein Skript für die hier erwähnte Lösung. Funktioniert am neuesten docker 1.10und docker-machine 0.6.0 gist.github.com/cristobal/fcb0987871d7e1f7449e
cristobal
@cristobal Es sieht so aus, als hätten Sie die Mount-Lösung als Skript geschrieben, nicht die Rsync-Lösung?
Andy
14

Im Moment sehe ich keine Möglichkeit, Volumes auf Computern bereitzustellen, daher besteht der Ansatz jetzt darin, die benötigten Dateien irgendwie auf den Computer zu kopieren oder zu synchronisieren.

Es gibt Gespräche darüber, wie dieses Problem im Github-Repo der Docker-Maschine gelöst werden kann. Jemand hat eine Pull-Anfrage gestellt, die scp auf der Docker-Maschine implementiert , und es ist bereits auf dem Master zusammengeführt, so dass es sehr wahrscheinlich ist, dass die nächste Version es enthalten wird.

Da es noch nicht veröffentlicht ist, würde ich empfehlen, dass Sie, wenn Sie Ihren Code auf github gehostet haben, einfach Ihr Repo klonen, bevor Sie die App ausführen

web:
  build: .
  command: git clone https://github.com/my/repo.git; ./repo/run_web.sh
  volumes:
    - .:/app
  ports:
    - "8000:8000"
  links:
    - db:db
    - rabbitmq:rabbit
    - redis:redis

Update: Bei näherer Betrachtung stellte ich fest, dass die Funktion bereits in den neuesten Binärdateien verfügbar ist. Wenn Sie diese erhalten, können Sie Ihr lokales Projekt kopieren, indem Sie einen Befehl wie den folgenden ausführen:

docker-machine scp -r . dev:/home/docker/project

Dies ist die allgemeine Form:

docker-machine scp [machine:][path] [machine:][path]

So können Sie Dateien von, zu und zwischen Computern kopieren.

Prost! 1

claudevandort
quelle
die Dokumentation für Docker-Maschine scp: docs.docker.com/machine/reference/scp
Anthony Dahanne
2
Diese Methode ist sehr langsam :(
Sergej Jevsejev
5

Seit Oktober 2017 gibt es einen neuen Befehl für die Docker-Maschine, der den Trick ausführt. Stellen Sie jedoch sicher, dass sich nichts im Verzeichnis befindet, bevor Sie es ausführen, da es sonst verloren gehen kann:

docker-machine mount <machine-name>:<guest-path> <host-path>

Weitere Informationen finden Sie in den Dokumenten: https://docs.docker.com/machine/reference/mount/

PR mit der Änderung: https://github.com/docker/machine/pull/4018

Jorge
quelle
1
Unglaublicherweise ist es aus der Docker Machine-Dokumentation (die Sie verlinkt haben) buchstäblich unmöglich zu wissen, dass die Reihenfolge im Befehl ist ...:<guest-path> <host-path>(und nicht umgekehrt). So etwas Einfaches und Kritisches ist in der Dokumentation zu vermerken ... ist es einfach nicht!
Dan Nissenbaum
Ich denke, es ist nicht sehr explizit, Sie haben Recht. Es muss aus der Liste der Befehle erraten werden
Jorge
Es macht den Trick, aber auf andere Weise. Es ermöglicht das Mounten des Docker-Maschinenverzeichnisses auf Ihrem lokalen Computer. Leider erlaubt es keinen anderen Weg :(
Ravenwing
4

Wenn Sie die Option rsync mit Docker-Maschine wählen, können Sie sie mit dem folgenden docker-machine ssh <machinename>Befehl kombinieren :

rsync -rvz --rsh='docker-machine ssh <machinename>' --progress <local_directory_to_sync_to> :<host_directory_to_sync_to>

Es verwendet dieses Befehlsformat von rsync und lässt HOSTleer:

rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST

( http://linuxcommand.org/man_pages/rsync1.html )

dmh
quelle
1

Schließlich haben Sie herausgefunden, wie Sie die Windows Docker Toolbox auf Version 1.12.5 aktualisieren und meine Volumes am Laufen halten können, indem Sie einen freigegebenen Ordner im Oracle VM VirtualBoxManager hinzufügen und die Pfadkonvertierung deaktivieren. Wenn Sie Windows 10+ haben, verwenden Sie am besten den neueren Docker für Windows.

1. das Upgrade Schmerz:

  1. Deinstallieren Sie zuerst VirtualBox.
    • Ja, das kann in anderen Tools wie Android Studio zu Problemen führen. Danke Docker :(
  2. Installieren Sie eine neue Version der Docker Toolbox.

Beispiel für eine Redis-Datenbank: redis: image: redis:alpine container_name: redis ports: - "6379" volumes: - "/var/db/redis:/data:rw"

Im Docker-Schnellstart-Terminal ....

  1. run docker-machine stop default- Stellen Sie sicher, dass die VM beschädigt ist

In Oracle VM VirtualBox Manager ...

  1. Ein freigegebener Ordner in der defaultVM wurde über oder über die Befehlszeile hinzugefügt
    • D:\Projects\MyProject\db => /var/db

In docker-compose.yml...

  1. Zugeordnetes Redis-Volumen als: "/var/db/redis:/data:rw"

Im Docker-Schnellstart-Terminal ....

  1. Set COMPOSE_CONVERT_WINDOWS_PATHS=0(für Toolbox-Version> = 1.9.0)
  2. Führen Sie diese aus docker-machine start default, um die VM neu zu starten.
  3. cd D:\Projects\MyProject\
  4. docker-compose up sollte jetzt funktionieren.

Jetzt wird die Redis-Datenbank in erstellt D:\Projects\MyProject\db\redis\dump.rdb

Warum relative Hostpfade vermeiden?

Ich habe relative Hostpfade für Windows Toolbox vermieden, da sie möglicherweise ungültige '\' Zeichen einführen. Es ist nicht so schön wie das Verwenden von Pfaden im Vergleich zu, docker-compose.ymlaber zumindest meine Kollegen können es problemlos tun, selbst wenn sich ihr Projektordner an einer anderen Stelle befindet, ohne die docker-compose.ymlDatei hacken zu müssen (schlecht für SCM).

Ursprüngliches Problem

Zu Ihrer Information ... Hier ist der ursprüngliche Fehler, den ich erhalten habe, als ich schöne, saubere relative Pfade verwendet habe, die früher für ältere Versionen einwandfrei funktionierten. Früher war meine Volumenzuordnung gerecht"./db/redis:/data:rw"

ERROR: for redis Cannot create container for service redis: Invalid bind mount spec "D:\\Projects\\MyProject\\db\\redis:/data:rw": Invalid volume specification: 'D:\Projects\MyProject\db\redis:/data

Dies bricht aus zwei Gründen ..

  1. Es kann nicht auf das D:Laufwerk zugreifen
  2. Volume-Pfade dürfen keine \Zeichen enthalten
    • docker-compose fügt sie hinzu und beschuldigt dich dann dafür !!
    • Verwenden Sie COMPOSE_CONVERT_WINDOWS_PATHS=0, um diesen Unsinn zu stoppen.

Ich empfehle, Ihre zusätzliche Zuordnung von freigegebenen VM-Ordnern in Ihrer docker-compose.ymlDatei zu dokumentieren, da Sie VirtualBox möglicherweise erneut deinstallieren und den freigegebenen Ordner zurücksetzen müssen. Ihre Kollegen werden Sie trotzdem dafür lieben.

Tony O'Hagan
quelle
Sie, Sir, sind eine gute Person
AaronHS
1

Alle anderen Antworten waren für die damalige Zeit gut, aber jetzt (Docker Toolbox v18.09.3) funktioniert alles sofort. Sie müssen lediglich einen freigegebenen Ordner zur VirtualBox-VM hinzufügen.

Docker Toolbox wird automatisch C:\Usersals freigegebener Ordner /c/Usersunter einem virtuellen Linux-Computer hinzugefügt (mithilfe der Funktion "Freigegebene Ordner" von Virtual Box). Wenn sich Ihre docker-compose.ymlDatei also irgendwo unter diesem Pfad befindet und Sie die Verzeichnisse des Host-Computers nur unter diesem Pfad bereitstellen, sollten alle sofort funktionieren.

Beispielsweise:

C:\Users\username\my-project\docker-compose.yml::

...
  volumes:
    - .:/app
...

Der .Pfad wird automatisch in einen absoluten Pfad C:\Users\username\my-projectund dann in konvertiert /c/Users/username/my-project. Und genau so wird dieser Pfad aus der Sicht der virtuellen Linux-Maschine gesehen (Sie können ihn überprüfen: docker-machine sshund dann ls /c/Users/username/my-project). Das endgültige Reittier wird also sein/c/Users/username/my-project:/app .

Alles funktioniert transparent für Sie.

Dies funktioniert jedoch nicht, wenn sich Ihr Host-Mount-Pfad nicht unter dem C:\UsersPfad befindet. Zum Beispiel, wenn Sie das gleiche docker-compose.ymlunter setzen D:\dev\my-project.

Dies kann jedoch leicht behoben werden.

  1. Stoppen Sie die virtuelle Maschine ( docker-machine stop).
  2. Öffnen Sie die Virtual Box-Benutzeroberfläche, öffnen Sie die Einstellungen der benannten virtuellen Maschine default, öffnen Sie den Shared FoldersAbschnitt und fügen Sie den neuen freigegebenen Ordner hinzu:

    • Ordnerpfad: D:\dev
    • Ordnernamen: d/dev

    Drücken Sie OKzweimal und schließen Sie die Virtual Box-Benutzeroberfläche.

  3. Starten Sie die virtuelle Maschine ( docker-machine start).

Das ist alles. Alle Pfade des Hostcomputers unter D:\devsollten jetzt in docker-compose.ymlMounts funktionieren .

Ruslan Stelmachenko
quelle
1

Es kann getan Hexe Kombination aus drei Tools sein: docker-machine mount, rsync,inotifywait

TL; DR

Skript basierend auf allen unten ist hier

Nehmen wir an, Sie haben Ihre docker-compose.ymlund run_web.shin/home/jdcaballerov/web

  1. Mounten Sie das Verzeichnis auf dem Computer, der denselben Pfad hat wie auf Ihrem Hostdocker-machine machine:/home/jdcaballerov/web /tmp/some_random_dir
  2. Synchronisieren Sie das gemountete Verzeichnis mit dir auf Ihrem Host rsync -r /home/jdcaballerov/web /tmp/some_random_dir
  3. Bei jeder Änderung von Dateien in Ihrem Verzeichnis synchronisieren:

    inotifywait -r -m -e close_write --format '%w%f' /home/jdcaballerov/web | while read CHANGED_FILE
    do
        rsync /home/jdcaballerov/web /tmp/some_random_dir
    done
    

ACHTUNG - es gibt zwei Verzeichnisse mit demselben Pfad - eines befindet sich auf Ihrem lokalen (Host-) Computer, das zweite auf einem Docker-Computer.

Rabenflügel
quelle
0

Ich gehe davon aus, dass sich die run_web.shDatei im selben Verzeichnis befindet wie Ihre docker-compose.ymlDatei. Dann sollte der Befehl sein command: /app/run_web.sh.

Es sei denn, das Dockerfile(das Sie nicht offenlegen) kümmert sich darum, die run_web.shDatei in das Docker-Image zu legen .

Thomasleveil
quelle
Danke für deine Antwort. Es befindet sich im selben Verzeichnis. Ich stelle jedoch fest, dass das Volume nicht gemountet wird. Dateien sind nicht verfügbar, und das ist die Frage. Wie man sie hinzufügt. Die Struktur ist ähnlich zu syncano.com/…
jdcaballerov
Stellen Sie sicher, dass Sie die neuesten Versionen von Docker und Dicker-Compose haben.
Thomasleveil
Docker: Docker Version 1.6.0, Build 4749651, Docker-Maschine Version 0.2.0 (8b9eaf2), Docker-Compose 1.2.0
jdcaballerov
Haben Sie die Docker-Datei von syncano.com/… in irgendeiner Weise geändert ?
Thomasleveil
1
Ja, ich füge den Code hinzu und erstelle das Verzeichnis. Das Problem ist, dass Docker-Compose beim Ausführen das Volume überschreibt: Volumes: - .: / App und ein leeres Verzeichnis hinterlässt. Ich habe Bände in Compose kommentiert und es funktioniert.
jdcaballerov
0

Nachdem Sie die Beiträge hier zusammengefasst haben, fügen Sie ein aktualisiertes Skript hinzu, um beim Neustart von Virtualbox einen zusätzlichen Host-Mount-Punkt und eine automatische Bereitstellung zu erstellen. Die Arbeitsumgebung ist wie folgt kurz: - Windows 7 - docker-machine.exe Version 0.7.0 - VirtualBox 5.0.22

    #!env bash

    : ${NAME:=default}
    : ${SHARE:=c/Proj}
    : ${MOUNT:=/c/Proj}
    : ${VBOXMGR:=C:\Program Files\Oracle\VirtualBox\VBoxManage.exe}
    SCRIPT=/mnt/sda1/var/lib/boot2docker/bootlocal.sh

    ## set -x
    docker-machine stop $NAME
    "$VBOXMGR" sharedfolder add $NAME --name c/Proj --hostpath 'c:\' --automount 2>/dev/null || :
    docker-machine start $NAME
    docker-machine env $NAME

    docker-machine ssh $NAME 'echo "mkdir -p $MOUNT" | sudo tee $SCRIPT'
    docker-machine ssh $NAME 'echo "sudo mount -t vboxsf -o rw,user $SHARE $MOUNT" |  sudo tee -a $SCRIPT'
    docker-machine ssh $NAME 'sudo chmod +x /mnt/sda1/var/lib/boot2docker/bootlocal.sh'
    docker-machine ssh $NAME 'sudo /mnt/sda1/var/lib/boot2docker/bootlocal.sh'
    #docker-machine ssh $NAME 'ls $MOUNT'
Jesse
quelle
0

Ich verwende Docker-Maschine 0.12.2 mit dem Virtualbox-Laufwerk auf meinem lokalen Computer. Ich habe festgestellt, dass es ein Verzeichnis gibt, /hosthome/$(user name)von dem aus Sie auf lokale Dateien zugreifen können.

Benjamin Slabbert
quelle
0

Ich dachte nur, ich würde erwähnen, dass ich 18.03.1-ce-win65 (17513) unter Windows 10 verwendet habe, und ich habe festgestellt, dass, wenn Sie zuvor ein Laufwerk freigegeben und die Anmeldeinformationen zwischengespeichert haben, sobald Sie Ihren Kennwort-Docker geändert haben Die in Containern montierten Volumes sind leer.

Es gibt keinen Hinweis darauf, dass tatsächlich passiert, dass jetzt kein Zugriff auf die mit den alten zwischengespeicherten Anmeldeinformationen freigegebenen Anmeldeinformationen möglich ist. Die Lösung in diesem Szenario besteht darin, die Anmeldeinformationen entweder über die Benutzeroberfläche (Einstellungen-> Freigegebene Laufwerke) zurückzusetzen oder die Laufwerksfreigabe zu deaktivieren und dann neu zu aktivieren und das neue Kennwort einzugeben.

Es wäre nützlich, wenn Docker-Compose in diesen Situationen einen Fehler verursachen würde.

nrjohnstone
quelle