Comment monter des volumes locaux sur une machine docker


85

J'essaye d'utiliser docker-machine avec docker-compose. Le fichier docker-compose.yml a les définitions suivantes:

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

Lors de l'exécution, docker-compose up -dtout va bien jusqu'à ce que vous essayiez d'exécuter la commande et qu'une erreur se produise:

Impossible de démarrer le conteneur b58e2dfa503b696417c1c3f49e2714086d4e9999bd71915a53502cb6ef43936d: [8] Erreur système: exec: "./run_web.sh": stat ./run_web.sh: aucun fichier ou répertoire de ce type

Les volumes locaux ne sont pas montés sur la machine distante. Quelle est la stratégie recommandée pour monter les volumes locaux avec le code des webapps?


La structure du projet et de docker-compose.yml est similaire à ce tutoriel syncano.com
...

1
Cela devrait être dans les documents docker-compose comme un conseil utile à ceux qui pourraient commencer à utiliser compose localement. M'aurait sauvé des heures de moments WTF en essayant de comprendre pourquoi diable mon chemin de fichier était faux ou introuvable. Non, je me sens juste idiot.
timbrown

Réponses:


93

Docker-machine monte automatiquement le répertoire des utilisateurs ... Mais parfois, cela ne suffit pas.

Je ne sais pas docker 1.6, mais 1.8 vous PEUX ajouter un montage supplémentaire pour docker machine

Ajouter un point de montage de machine virtuelle (partie 1)

CLI : (ne fonctionne que lorsque la machine est arrêtée)

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

Ainsi, un exemple dans Windows serait

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

GUI : (ne nécessite PAS l'arrêt de la machine)

  1. Démarrez "Oracle VM VirtualBox Manager"
  2. Clic-droit <machine name> (par défaut)
  3. Réglages...
  4. Dossiers partagés
  5. Le dossier + icône sur la droite (Ajouter un partage)
  6. Chemin du dossier: <host dir> (e :)
  7. Nom de dossier: <mount name> (e)
  8. Cochez "Auto-mount" et "Make Permanent" (Lecture uniquement si vous le souhaitez ...) (Le montage automatique est en quelque sorte inutile actuellement ...)

Montage dans boot2docker (partie 2)

Monter manuellement dans boot2docker :

  1. Il existe différentes manières de se connecter, d'utiliser "Show" dans "Oracle VM VirtualBox Manager", ou ssh / putty dans docker par adresse IP docker-machine ip default, etc ...
  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>

Mais ce n'est bon que jusqu'au redémarrage de la machine, puis le montage est perdu ...

Ajout d'un montage automatique à boot2docker :

Lors de la connexion à la machine

  1. Modifier / créer (en tant que root) /mnt/sda1/var/lib/boot2docker/bootlocal.sh, sda1 peut être différent pour vous ...
  2. Ajouter

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

Avec ces changements, vous devriez avoir un nouveau point de montage. C'est l'un des rares fichiers que j'ai pu trouver qui est appelé au démarrage et qui est persistant. Jusqu'à ce qu'il y ait une meilleure solution, cela devrait fonctionner.


Ancienne méthode: moins recommandée , mais laissée comme alternative

  • Edit (en tant que root) /mnt/sda1/var/lib/boot2docker/profile, sda1 peut être différent pour vous ...
  • Ajouter

    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>
    

En dernier recours , vous pouvez prendre l'alternative un peu plus fastidieuse, et vous pouvez simplement modifier l'image de démarrage.

  • git -c core.autocrlf=false clone https://github.com/boot2docker/boot2docker.git
  • cd boot2docker
  • git -c core.autocrlf=false checkout v1.8.1 #ou votre version appropriée
  • Éditer rootfs/etc/rc.d/automount-shares
  • Ajoutez une try_mount_share <local_dir> <mount_name>ligne juste avant fi à la fin. Par exemple

    try_mount_share /e e
    

    Assurez-vous simplement de ne pas définir le sur quoi que ce soit dont le système d'exploitation a besoin, comme / bin, etc ...

  • docker build -t boot2docker . #Cela prendra environ une heure la première fois :(
  • docker run --rm boot2docker > boot2docker.iso
  • Sauvegardez l'ancien boot2docker.iso et copiez le nouveau à sa place, dans ~ / .docker / machine / machines /

Ça marche, c'est juste long et compliqué

docker version 1.8.1, version 0.4.0 de docker-machine


Pour tous ceux qui ont des problèmes avec cela, je suis presque sûr que je devais faire correspondre les chemins locaux à ceux de la machine docker. De plus, docker-compose semblait réussir à monter les volumes alors que docker ordinaire ne le faisait pas - je ne sais pas pourquoi.
espionné

3
Création d'un script pour la solution mentionnée ici. Fonctionne sur les derniers docker 1.10 et docker-machine 0.6.0 gist.github.com/cristobal/fcb0987871d7e1f7449e
cristobal

Différentes ressources parlent de l'utilisation /mnt/sda1/var/lib/boot2docker/profile, pouvez-vous expliquer pourquoi vous êtes passé à l'utilisation /mnt/sda1/var/lib/boot2docker/bootlocal.sh? De plus, parcourir autant de texte ne contribue pas à la lisibilité de votre réponse ;-)
Forage

1
@Forage Point pris sur mon formatage :). Je ne me souviens plus de la raison pour laquelle je suggère la bootlocal.shméthode. Tout ce que je peux dire, c'est qu'il semble plus propre d'utiliser simplement une commande de montage comme je l'ai bootlocal.shfait dans le profil. De plus, généralement, je pense que le profilepeut être exécuté plusieurs fois et qu'un montage ne doit être exécuté qu'une seule fois, donc cela a plus de sens. Mais les deux peuvent fonctionner.
Andy

AIMER! Merci!
Qorbani

28

Également rencontré ce problème et il semble que les volumes locaux ne sont pas montés lors de l'utilisation de docker-machine. Une solution de piratage consiste à

  1. obtenir le répertoire de travail actuel de l'instance docker-machine docker-machine ssh <name> pwd

  2. utiliser un outil de ligne de commande comme rsyncpour copier un dossier sur un système distant

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

Le pwd par défaut est / root donc la commande ci-dessus serait rsync -avzhe ssh --progress <name_of_folder> username@remote_ip:/root

NB: vous devrez fournir le mot de passe du système distant. Vous pouvez rapidement en créer un par ssh dans le système distant et créer un mot de passe.

  1. changer le point de montage du volume dans votre docker-compose.ymlfichier de .:/appà/root/<name_of_folder>:/app

  2. courir docker-compose up -d

NB lorsque des modifications sont effectuées localement, n'oubliez pas de réexécuter rsyncpour pousser les modifications vers le système distant.

Ce n'est pas parfait mais ça marche. Un problème est en cours https://github.com/docker/machine/issues/179

Les autres projets qui tentent de résoudre ce problème incluent docker-rsync


rsync doit être installé sur un système distant il semble `sh: rsync: not found rsync: connexion inopinément fermée (0 octet reçu jusqu'à présent) [sender] erreur rsync: commande distante non trouvée (code 127) dans / SourceCache / rsync / rsync -45 / rsync / io.c (453) [sender = 2.6.9] `Comment l'avez-vous fait fonctionner?
krinker le

1
rsync doit être installé sur votre système local
gbozee

L'utilisation de ces étapes verrouille complètement mon hôte digitalocean. Les fichiers sont transférés très bien, mais lorsque j'essaie de me reconnecter à l'hôte avec docker-machine, je exit status 255dois recréer complètement la machine.
dsifford le

1
Création d'un script pour la solution mentionnée ici. Fonctionne sur les derniers docker 1.10et docker-machine 0.6.0 gist.github.com/cristobal/fcb0987871d7e1f7449e
cristobal

@cristobal, il semble que vous ayez écrit la solution de montage, pas la solution rsync?
Andy

14

Pour le moment, je ne vois pas vraiment de moyen de monter des volumes sur des machines, donc l'approche à présent serait de copier ou de synchroniser les fichiers dont vous avez besoin dans la machine.

Il y a des conversations sur la façon de résoudre ce problème sur le dépôt github de la machine docker. Quelqu'un a fait une pull request implémentant scp sur docker-machine et il est déjà fusionné sur master, il est donc très probable que la prochaine version l'inclura.

Comme il n'est pas encore publié, je recommanderais maintenant que si votre code est hébergé sur github, clonez simplement votre dépôt avant d'exécuter l'application.

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

Mise à jour: En regardant plus loin, j'ai constaté que la fonctionnalité est déjà disponible dans les derniers binaires , lorsque vous les obtenez, vous pourrez copier votre projet local en exécutant une commande comme celle-ci:

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

Étant la forme générale:

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

Ainsi, vous pouvez copier des fichiers depuis, vers et entre des machines.

Bravo! 1


la documentation pour docker-machine scp: docs.docker.com/machine/reference/scp
Anthony Dahanne

2
cette méthode est très lente :(
Sergej Jevsejev

5

Depuis octobre 2017, il existe une nouvelle commande pour docker-machine qui fait l'affaire, mais assurez-vous qu'il n'y a rien dans le répertoire avant de l'exécuter, sinon il risque de se perdre:

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

Consultez la documentation pour plus d'informations: https://docs.docker.com/machine/reference/mount/

PR avec le changement: https://github.com/docker/machine/pull/4018


1
Tout simplement incroyable, à partir de la documentation de Docker Machine (que vous avez liée), il est - littéralement - impossible de savoir que l'ordre dans la commande est ...:<guest-path> <host-path>(plutôt que l'inverse). Quelque chose d'aussi simple et critique que cela à noter dans la documentation ... ne l'est tout simplement pas!
Dan Nissenbaum

Je suppose que ce n'est pas très explicite, vous avez raison. Il doit être deviné à partir de la liste des commandes
Jorge

Cela fait l'affaire, mais d'une autre manière. Il permet de monter le répertoire docker-machine sur votre machine locale. Malheureusement, cela ne permet pas d'autre moyen :(
ravenwing

4

Si vous choisissez l'option rsync avec docker-machine, vous pouvez la combiner avec la docker-machine ssh <machinename>commande comme ceci:

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

Il utilise ce format de commande de rsync, en laissant HOSTvide:

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

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


1

Enfin compris comment mettre à niveau Windows Docker Toolbox vers la v1.12.5 et maintenir mes volumes en état de fonctionnement en ajoutant un dossier partagé dans le Oracle VM VirtualBoxgestionnaire et en désactivant la conversion de chemin. Si vous avez Windows 10+, il est préférable d'utiliser le plus récent Docker pour Windows.

1er la douleur de mise à niveau:

  1. Désinstallez d'abord VirtualBox.
    • Oui, cela peut casser des éléments dans d'autres outils comme Android Studio. Merci Docker :(
  2. Installez la nouvelle version de Docker Toolbox.

Exemple de base de données Redis: redis: image: redis:alpine container_name: redis ports: - "6379" volumes: - "/var/db/redis:/data:rw"

Dans Docker Quickstart Terminal ...

  1. run docker-machine stop default- Assurez-vous que la VM est haultée

Dans Oracle VM VirtualBox Manager ...

  1. Ajout d'un dossier partagé dans la defaultVM via ou en ligne de commande
    • D:\Projects\MyProject\db => /var/db

Dans docker-compose.yml...

  1. Volume redis mappé comme: "/var/db/redis:/data:rw"

Dans Docker Quickstart Terminal ...

  1. Set COMPOSE_CONVERT_WINDOWS_PATHS=0(pour la version Toolbox> = 1.9.0)
  2. exécutez docker-machine start defaultpour redémarrer la machine virtuelle.
  3. cd D:\Projects\MyProject\
  4. docker-compose up devrait fonctionner maintenant.

Crée maintenant la base de données redis dans D:\Projects\MyProject\db\redis\dump.rdb

Pourquoi éviter les chemins d'hôte relatifs?

J'ai évité les chemins d'hôte relatifs pour Windows Toolbox car ils peuvent introduire des caractères «\» non valides. Ce n'est pas aussi agréable que d'utiliser des chemins relatifs à docker-compose.ymlmais au moins mes collègues développeurs peuvent le faire facilement même si leur dossier de projet est ailleurs sans avoir à pirater le docker-compose.ymlfichier (mauvais pour SCM).

Édition originale

FYI ... Voici l'erreur d'origine que j'ai eue lorsque j'ai utilisé de jolis chemins relatifs propres qui fonctionnaient très bien pour les anciennes versions. Mon mappage de volume était juste"./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

Cela rompt pour deux raisons.

  1. Il ne peut pas accéder au D:lecteur
  2. Les chemins de volume ne peuvent pas inclure de \caractères
    • docker-compose les ajoute et vous en blâme !!
    • Utilisez COMPOSE_CONVERT_WINDOWS_PATHS=0pour arrêter ce non-sens.

Je vous recommande de documenter votre mappage de dossier partagé VM supplémentaire dans votre docker-compose.ymlfichier car vous devrez peut-être désinstaller à nouveau VirtualBox et réinitialiser le dossier partagé et de toute façon vos collègues développeurs vous adoreront pour cela.


vous monsieur, êtes une bonne personne
AaronHS

1

Toutes les autres réponses étaient bonnes pour l'époque, mais maintenant (Docker Toolbox v18.09.3) tout fonctionne hors de la boîte. Il vous suffit d'ajouter un dossier partagé dans VirtualBox VM.

Docker Toolbox ajoute automatiquement en C:\Userstant que dossier partagé /c/Userssous la machine virtuelle Linux (en utilisant la fonction de dossiers partagés de Virtual Box), donc si votre docker-compose.ymlfichier se trouve quelque part sous ce chemin et que vous montez les répertoires de la machine hôte uniquement sous ce chemin, tout devrait fonctionner immédiatement.

Par exemple:

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

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

Le .chemin sera automatiquement converti en chemin absolu C:\Users\username\my-project, puis en /c/Users/username/my-project. Et c'est exactement ainsi que ce chemin est vu du point de vue de la machine virtuelle Linux (vous pouvez le vérifier: docker-machine sshet ensuite ls /c/Users/username/my-project). Ainsi, le montage final sera/c/Users/username/my-project:/app .

Tout fonctionne de manière transparente pour vous.

Mais cela ne fonctionne pas si le chemin de montage de votre hôte n'est pas sous le C:\Userschemin. Par exemple, si vous mettez le même docker-compose.ymlsous D:\dev\my-project.

Cela peut être résolu facilement.

  1. Arrêtez la machine virtuelle ( docker-machine stop).
  2. Ouvrez l'interface graphique de Virtual Box, ouvrez les paramètres de la machine virtuelle nommée default, ouvrez la Shared Folderssection et ajoutez le nouveau dossier partagé:

    • Chemin du dossier: D:\dev
    • Nom de dossier: d/dev

    Appuyez OKdeux fois et fermez l'interface graphique de Virtual Box.

  3. Démarrez la machine virtuelle ( docker-machine start).

C'est tout. Tous les chemins de la machine hôte sous D:\devdevraient maintenant fonctionner dans les docker-compose.ymlmontages.


1

Il peut être fait combinaison de sorcière de trois outils: docker-machine mount, rsync,inotifywait

TL; DR

Le script basé sur tout ce qui suit est ici

Disons que vous avez votre docker-compose.ymlet run_web.shdans/home/jdcaballerov/web

  1. Répertoire de montage sur la machine qui a le même chemin que vous l'avez sur votre hôtedocker-machine machine:/home/jdcaballerov/web /tmp/some_random_dir
  2. Synchronisez le répertoire monté avec dir sur votre hôte rsync -r /home/jdcaballerov/web /tmp/some_random_dir
  3. Synchronisez à chaque changement de fichiers dans votre répertoire:

    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
    

ATTENTION - il y a deux répertoires qui ont le même chemin - l'un est sur votre machine locale (hôte), le second sur la machine docker.


0

Je suppose que le run_web.shfichier est dans le même répertoire que votre docker-compose.ymlfichier. Alors la commande devrait être command: /app/run_web.sh.

À moins Dockerfileque (que vous ne divulguez) ne s'occupe de placer le run_web.shfichier dans l'image Docker.


Merci pour votre réponse. C'est sur le même répertoire. Cependant je remarque que le volume n'est pas monté. Les fichiers ne sont pas disponibles, et c'est la question. Comment les ajouter. La structure est similaire à syncano.com
...

Assurez-vous que vous disposez des dernières versions de docker et de dicker-compose.
Thomasleveil

docker: Docker version 1.6.0, build 4749651, docker-machine version 0.2.0 (8b9eaf2), docker-compose 1.2.0
jdcaballerov

Avez-vous modifié le Dockerfile de syncano.com/ ... d'une manière ou d'une autre?
Thomasleveil

1
Oui, j'ajoute le code, crée le répertoire. Le problème est que lorsque docker-compose s'exécute, il écrase le volume: volumes: -.: / App et laisse un répertoire vide. J'ai commenté des volumes en composition et ça marche.
jdcaballerov

0

Après avoir résumé les articles ici, un script mis à jour joint, pour créer un point de montage hôte supplémentaire et un montage automatique au redémarrage de Virtualbox. Le bref environnement de travail comme ci-dessous: - 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'

0

J'utilise docker-machine 0.12.2 avec le lecteur virtualbox sur ma machine locale. J'ai trouvé qu'il existe un répertoire à /hosthome/$(user name)partir duquel vous avez accès aux fichiers locaux.


0

Je pensais juste que je mentionnerais que j'utilisais 18.03.1-ce-win65 (17513) sur Windows 10 et j'ai remarqué que si vous avez déjà partagé un lecteur et mis en cache les informations d'identification, une fois que vous avez changé votre mot de passe, le docker commencera à avoir les volumes montés dans des conteneurs comme vierges.

Cela ne donne aucune indication que ce qui se passe réellement, c'est qu'il ne parvient pas à accéder au partage avec les anciennes informations d'identification mises en cache. La solution dans ce scénario consiste à réinitialiser les informations d'identification via l'interface utilisateur (Paramètres-> Lecteurs partagés) ou à désactiver puis le partage de lecteur renouvelable et à entrer le nouveau mot de passe.

Il serait utile que docker-compose donne une erreur dans ces situations.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.