Cómo montar volúmenes locales en la máquina docker

85

Estoy tratando de usar docker-machine con docker-compose. El archivo docker-compose.yml tiene las siguientes definiciones:

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

Al ejecutar docker-compose up -dtodo va bien hasta intentar ejecutar el comando y se produce un error:

No se puede iniciar el contenedor b58e2dfa503b696417c1c3f49e2714086d4e9999bd71915a53502cb6ef43936d: [8] Error del sistema: exec: "./run_web.sh": stat ./run_web.sh: no existe ese archivo o directorio

Los volúmenes locales no están montados en la máquina remota. ¿Cuál es la estrategia recomendada para montar los volúmenes locales con el código de las aplicaciones web?

jdcaballerov
fuente
La estructura del proyecto y docker-compose.yml es similar a este tutorial syncano.com/…
jdcaballerov
1
Esto debería estar en los documentos de docker-compose como una sugerencia útil para aquellos que podrían estar comenzando a usar compose localmente. Me habría ahorrado horas de momentos WTF tratando de averiguar por qué diablos la ruta de mi archivo era incorrecta o no se encontraba. No, solo me siento tonto.
Timbrown

Respuestas:

93

Docker-machine monta automáticamente el directorio de usuarios ... Pero a veces eso no es suficiente.

No sé sobre docker 1.6, pero en 1.8 PUEDES agregar un soporte adicional a docker-machine

Agregar punto de montaje de máquina virtual (parte 1)

CLI : (solo funciona cuando la máquina está parada)

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

Entonces, un ejemplo en Windows sería

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

GUI : (NO requiere que la máquina se detenga)

  1. Inicie "Oracle VM VirtualBox Manager"
  2. Clic derecho <machine name>(predeterminado)
  3. Configuraciones ...
  4. Carpetas compartidas
  5. El ícono Carpeta + a la derecha (Agregar recurso compartido)
  6. Ruta de la carpeta: <host dir>(e :)
  7. Nombre de carpeta: <mount name>(e)
  8. Marque "Auto-mount" y "Make Permanent" (Lea solo si lo desea ...) (El auto-mount no tiene sentido actualmente ...)

Montaje en boot2docker (parte 2)

Montar manualmente en boot2docker :

  1. Hay varias formas de iniciar sesión, usar "Mostrar" en "Oracle VM VirtualBox Manager", o ssh / putty en la ventana acoplable por dirección 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>

Pero esto solo es bueno hasta que reinicia la máquina, y luego se pierde el soporte ...

Añadiendo un montaje automático a boot2docker :

Mientras está conectado a la máquina

  1. Edite / cree (como root) /mnt/sda1/var/lib/boot2docker/bootlocal.sh, sda1 puede ser diferente para usted ...
  2. Añadir

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

Con estos cambios, debería tener un nuevo punto de montaje. Este es uno de los pocos archivos que pude encontrar que se llama al arrancar y es persistente. Hasta que haya una solución mejor, esto debería funcionar.


Método antiguo: menos recomendado , pero dejado como alternativa

  • Edite (como root) /mnt/sda1/var/lib/boot2docker/profile, sda1 puede ser diferente para usted ...
  • Añadir

    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>
    

Como último recurso , puede tomar la alternativa un poco más tediosa y puede modificar la imagen de arranque.

  • git -c core.autocrlf=false clone https://github.com/boot2docker/boot2docker.git
  • cd boot2docker
  • git -c core.autocrlf=false checkout v1.8.1 #o su versión apropiada
  • Editar rootfs/etc/rc.d/automount-shares
  • Agregue una try_mount_share <local_dir> <mount_name>línea justo antes de fi al final. Por ejemplo

    try_mount_share /e e
    

    Solo asegúrese de no configurar nada que el sistema operativo necesite, como / bin, etc.

  • docker build -t boot2docker . # Esto tomará aproximadamente una hora la primera vez :(
  • docker run --rm boot2docker > boot2docker.iso
  • Haga una copia de seguridad del antiguo boot2docker.iso y copie el nuevo en su lugar, en ~ / .docker / machine / machines /

Esto funciona, es largo y complicado

docker versión 1.8.1, docker-machine versión 0.4.0

Andy
fuente
Para cualquiera que tenga problemas con esto, estoy bastante seguro de que tuve que hacer que las rutas locales coincidieran con las de la máquina acoplable. Además, docker-compose pareció tener éxito en montar los volúmenes, mientras que el docker normal no lo hizo, no estoy seguro de por qué.
spieden
3
Creó un script para la solución mencionada aquí. Funciona en los últimos Docker 1.10 y Docker-Machine 0.6.0 gist.github.com/cristobal/fcb0987871d7e1f7449e
cristobal
Diferentes recursos hablan sobre el uso /mnt/sda1/var/lib/boot2docker/profile, ¿puede explicar por qué cambió al uso /mnt/sda1/var/lib/boot2docker/bootlocal.sh? Además, tachar todo este texto no contribuye a la legibilidad de su respuesta ;-)
Forrage
1
@Forage Point tomado sobre mi formateo :). Ya no recuerdo por qué sugiero el bootlocal.shmétodo. Todo lo que puedo decir es que parece más limpio usar un comando de montaje como lo hice bootlocal.shen el perfil. Además, normalmente, creo que profilepodría ejecutarse varias veces, y una montura solo necesita ejecutarse una vez, por lo que tiene más sentido. Pero ambos pueden funcionar.
Andy
¡QUIÉRALO! ¡Gracias!
Qorbani
28

También encontré este problema y parece que los volúmenes locales no se montan cuando se usa docker-machine. Una solución de pirateo es

  1. obtener el directorio de trabajo actual de la instancia docker-machine docker-machine ssh <name> pwd

  2. use una herramienta de línea de comando como rsynccopiar la carpeta al sistema remoto

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

El pwd predeterminado es / root, por lo que el comando anterior sería rsync -avzhe ssh --progress <name_of_folder> username@remote_ip:/root

NB: deberá proporcionar la contraseña del sistema remoto. Puede crear uno rápidamente mediante ssh en el sistema remoto y crear una contraseña.

  1. cambie el punto de montaje del volumen en su docker-compose.ymlarchivo de .:/appa/root/<name_of_folder>:/app

  2. correr docker-compose up -d

NB cuando los cambios se realizan localmente, no olvide volver a ejecutar rsync a para enviar los cambios al sistema remoto.

No es perfecto pero funciona. Hay un problema en curso https://github.com/docker/machine/issues/179

Otro proyecto que intenta resolver esto incluye docker-rsync

gbozee
fuente
rsync debe instalarse en un sistema remoto, parece `sh: rsync: no encontrado rsync: conexión cerrada inesperadamente (0 bytes recibidos hasta ahora) [remitente] error de rsync: comando remoto no encontrado (código 127) en / SourceCache / rsync / rsync -45 / rsync / io.c (453) [sender = 2.6.9] `¿Cómo conseguiste que funcionara?
krinker
1
rsync debe instalarse en su sistema local
gbozee
El uso de estos pasos bloquea completamente mi host digitalocean. Los archivos se transfieren bien, pero cuando intento volver a conectarme al host con la máquina acoplable, obtengo exit status 255y tengo que recrear completamente la máquina.
dsifford
1
Creó un script para la solución mencionada aquí. Funciona en la última versióndocker 1.10 y en docker-machine 0.6.0 gist.github.com/cristobal/fcb0987871d7e1f7449e
cristobal
@cristobal, ¿parece que escribiste la solución de montaje, no la solución rsync?
Andy
14

Por el momento, realmente no veo ninguna forma de montar volúmenes en las máquinas, por lo que el enfoque ahora sería copiar o sincronizar de alguna manera los archivos que necesita en la máquina.

Hay conversaciones sobre cómo resolver este problema en el repositorio de github de la máquina docker. Alguien hizo una solicitud de extracción implementando scp en docker-machine y ya está fusionado en master, por lo que es muy probable que la próxima versión lo incluya.

Dado que aún no se ha lanzado, a estas alturas recomendaría que si tiene su código alojado en github, simplemente clone su repositorio antes de ejecutar la aplicación

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

Actualización: mirando más allá, descubrí que la función ya está disponible en los últimos binarios , cuando los obtenga, podrá copiar su proyecto local ejecutando un comando como este:

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

Siendo esta la forma general:

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

Para que pueda copiar archivos desde, hacia y entre máquinas.

¡Salud! 1

claudevandort
fuente
la documentación para docker-machine scp: docs.docker.com/machine/reference/scp
Anthony Dahanne
2
este método es muy lento :(
Sergej Jevsejev
5

Desde octubre de 2017, hay un nuevo comando para docker-machine que hace el truco, pero asegúrese de que no haya nada en el directorio antes de ejecutarlo, de lo contrario podría perderse:

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

Consulte los documentos para obtener más información: https://docs.docker.com/machine/reference/mount/

PR con el cambio: https://github.com/docker/machine/pull/4018

Jorge
fuente
1
Increíblemente, a partir de la documentación de Docker Machine (que vinculó), es, literalmente, imposible saber que el orden en el comando es ...:<guest-path> <host-path>(en lugar de al revés). Algo tan simple y crítico para tener en cuenta en la documentación ... ¡simplemente no lo es!
Dan Nissenbaum
Supongo que no es muy explícito, tienes razón. Hay que adivinarlo de la lista de comandos
Jorge
Hace el truco, pero de otra manera. Permite montar el directorio docker-machine en su máquina local. Desafortunadamente, no permite otra manera :(
ravenwing
4

Si elige la opción rsync con docker-machine, puede combinarla con el docker-machine ssh <machinename>comando de esta manera:

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

Utiliza este formato de comando de rsync, dejando en HOSTblanco:

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

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

dmh
fuente
1

Finalmente descubrí cómo actualizar Windows Docker Toolbox a v1.12.5 y mantener mis volúmenes funcionando agregando una carpeta compartida en el Oracle VM VirtualBoxadministrador y deshabilitando la conversión de ruta. Si tiene Windows 10+, es mejor usar el Docker más nuevo para Windows.

Primero el dolor de actualización:

  1. Desinstale VirtualBox primero.
    • Sí, eso puede romper cosas en otras herramientas como Android Studio. Gracias Docker :(
  2. Instale la nueva versión de Docker Toolbox.

Ejemplo de base de datos de Redis: redis: image: redis:alpine container_name: redis ports: - "6379" volumes: - "/var/db/redis:/data:rw"

En la terminal de inicio rápido de Docker ...

  1. ejecutar docker-machine stop default: asegúrese de que la máquina virtual sea transportada

En Oracle VM VirtualBox Manager ...

  1. Se agregó una carpeta compartida en la defaultVM a través de la línea de comando o
    • D:\Projects\MyProject\db => /var/db

En docker-compose.yml...

  1. Volumen de redis asignado como: "/var/db/redis:/data:rw"

En la terminal de inicio rápido de Docker ...

  1. Establecer COMPOSE_CONVERT_WINDOWS_PATHS=0(para la versión de Toolbox> = 1.9.0)
  2. ejecutar docker-machine start defaultpara reiniciar la VM.
  3. cd D:\Projects\MyProject\
  4. docker-compose up debería funcionar ahora.

Ahora crea la base de datos redis en D:\Projects\MyProject\db\redis\dump.rdb

¿Por qué evitar rutas de host relativas?

Yo evitaba caminos de acogida relativas para Windows Caja de herramientas, ya que pueden introducir no válidos '\' caracteres. No es tan agradable como usar rutas relativas a, docker-compose.ymlpero al menos mis compañeros desarrolladores pueden hacerlo fácilmente incluso si la carpeta de su proyecto está en otro lugar sin tener que piratear eldocker-compose.yml archivo (malo para SCM).

Emisión original

FYI ... Aquí está el error original que obtuve cuando usé buenas rutas relativas limpias que solían funcionar bien para versiones anteriores. Mi mapeo de volumen solía ser solo"./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

Esto se rompe por dos razones ...

  1. No puede acceder D: unidad
  2. Las rutas de volumen no pueden incluir \caracteres
    • docker-compose los agrega y luego te culpa por ello !!
    • Úsalo COMPOSE_CONVERT_WINDOWS_PATHS=0para detener esta tontería.

Recomiendo documentar su mapeo de carpeta compartida de VM adicional en su docker-compose.ymlarchivo, ya que es posible que deba desinstalar VirtualBox nuevamente y restablecer la carpeta compartida y, de todos modos, sus compañeros desarrolladores lo amarán por ello.

Tony O'Hagan
fuente
usted señor, es una buena persona
AaronHS
1

Todas las demás respuestas eran buenas para el momento, pero ahora (Docker Toolbox v18.09.3) todo funciona de inmediato. Solo necesita agregar una carpeta compartida en VirtualBox VM.

Docker Toolbox se agrega automáticamente C:\Userscomo carpeta compartida /c/Usersen la máquina virtual de Linux (utilizando la función de carpetas compartidas de Virtual Box), por lo que si su docker-compose.ymlarchivo se encuentra en algún lugar debajo de esta ruta y monta los directorios de la máquina host solo en esta ruta, todo debería funcionar de inmediato.

Por ejemplo:

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

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

La .ruta se convertirá automáticamente en ruta absoluta C:\Users\username\my-projecty luego en /c/Users/username/my-project. Y así es exactamente como se ve esta ruta desde el punto de vista de la máquina virtual linux (puede verificarlo: docker-machine sshy luego ls /c/Users/username/my-project). Entonces, el montaje final será /c/Users/username/my-project:/app.

Todo funciona de forma transparente para ti.

Pero esto no funciona si la ruta de montaje de su host no está debajo de la C:\Usersruta. Por ejemplo, si pones lo mismo docker-compose.ymldebajo D:\dev\my-project.

Sin embargo, esto se puede solucionar fácilmente.

  1. Detenga la máquina virtual ( docker-machine stop).
  2. Abra la GUI de Virtual Box, abra la Configuración de la máquina virtual nombrada default, abra la Shared Folderssección y agregue la nueva carpeta compartida:

    • Ruta de la carpeta: D:\dev
    • Nombre de la carpeta: d/dev

    Presione OKdos veces y cierre la GUI de Virtual Box.

  3. Inicie la máquina virtual ( docker-machine start).

Eso es todo. Todas las rutas de la máquina host debajo D:\devdeberían funcionar ahora en docker-compose.ymlmontajes.

Ruslan Stelmachenko
fuente
1

Puede ser combinado bruja hecho de tres herramientas: docker-machine mount, rsync,inotifywait

TL; DR

El script basado en todo lo que se muestra a continuación está aquí

Digamos que tienes tu docker-compose.ymly run_web.shen/home/jdcaballerov/web

  1. Monte el directorio en la máquina que tiene la misma ruta que la tiene en su hostdocker-machine machine:/home/jdcaballerov/web /tmp/some_random_dir
  2. Sincronice el directorio montado con dir en su host rsync -r /home/jdcaballerov/web /tmp/some_random_dir
  3. Sincronice cada cambio de archivos en su directorio:

    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
    

TENGA EN CUENTA : hay dos directorios que tienen la misma ruta: uno está en su máquina local (host), el segundo está en la máquina acoplable.

cuervo
fuente
0

Supongo que el run_web.sharchivo está en el mismo directorio que su docker-compose.ymlarchivo. Entonces el comando debería ser command: /app/run_web.sh.

A menos Dockerfileque (que no está revelando) se encargue de colocar el run_web.sharchivo en la imagen de Docker.

Thomasleveil
fuente
gracias por tu respuesta. Está en el mismo directorio. Sin embargo, noto que el volumen no se está montando. Los archivos no están disponibles y esa es la cuestión. Cómo agregarlos. La estructura es similar a syncano.com/…
jdcaballerov
Asegúrese de tener las últimas versiones de docker y dicker-compose.
Thomasleveil
docker: Docker versión 1.6.0, compilación 4749651, docker-machine versión 0.2.0 (8b9eaf2), docker-compose 1.2.0
jdcaballerov
¿Ha modificado el Dockerfile de syncano.com/… de alguna manera?
Thomasleveil
1
Sí, agrego el código, creo el directorio. El problema es que cuando se ejecuta docker-compose, sobrescribe el volumen: volúmenes: -.: / App y deja un directorio vacío. Comenté volúmenes en componer y funciona.
jdcaballerov
0

Después de resumir las publicaciones aquí, adjunte el script actualizado, para crear un punto de montaje de host adicional y un montaje automático cuando se reinicie Virtualbox. El resumen del entorno de trabajo es el siguiente: - Windows 7 - docker-machine.exe versión 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
fuente
0

Estoy usando docker-machine 0.12.2 con la unidad virtualbox en mi máquina local. Descubrí que hay un directorio /hosthome/$(user name)desde donde tiene acceso a los archivos locales.

Benjamin Slabbert
fuente
0

Solo pensé en mencionar que he estado usando 18.03.1-ce-win65 (17513) en Windows 10 y noté que si anteriormente compartió una unidad y guardó las credenciales en caché, una vez que cambie su contraseña, la ventana acoplable comenzará a tener los volúmenes montados dentro de los contenedores como en blanco.

No da ninguna indicación de que lo que realmente está sucediendo es que ahora no puede acceder a las credenciales compartidas con las antiguas en caché. La solución en este escenario es restablecer las credenciales a través de la interfaz de usuario (Configuración-> Unidades compartidas) o deshabilitar y luego renombrar el uso compartido de unidades e ingresar la nueva contraseña.

Sería útil si docker-compose mostrara un error en estas situaciones.

nrjohnstone
fuente