How to mount local volumes in docker machine
Asked Answered
L

12

90

I am trying to use docker-machine with docker-compose. The file docker-compose.yml has definitions as follows:

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

When running docker-compose up -d all goes well until trying to execute the command and an error is produced:

Cannot start container b58e2dfa503b696417c1c3f49e2714086d4e9999bd71915a53502cb6ef43936d: [8] System error: exec: "./run_web.sh": stat ./run_web.sh: no such file or directory

Local volumes are not mounted to the remote machine. Whats the recommended strategy to mount the local volumes with the webapps' code?

Landgrabber answered 4/5, 2015 at 21:58 Comment(2)
The structure of the project and docker-compose.yml is similar to this tutorial syncano.com/…Landgrabber
This should be in the docker-compose documents as a helpful hint to those that might be getting started using compose locally. Would have saved me hours of WTF moments trying to figure out why the heck my file path was wrong or not found. No I just feel silly.Befall
F
95

Docker-machine automounts the users directory... But sometimes that just isn't enough.

I don't know about docker 1.6, but in 1.8 you CAN add an additional mount to docker-machine

Add Virtual Machine Mount Point (part 1)

CLI: (Only works when machine is stopped)

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

So an example in windows would be

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

GUI: (does NOT require the machine be stopped)

  1. Start "Oracle VM VirtualBox Manager"
  2. Right-Click <machine name> (default)
  3. Settings...
  4. Shared Folders
  5. The Folder+ Icon on the Right (Add Share)
  6. Folder Path: <host dir> (e:)
  7. Folder Name: <mount name> (e)
  8. Check on "Auto-mount" and "Make Permanent" (Read only if you want...) (The auto-mount is sort of pointless currently...)

Mounting in boot2docker (part 2)

Manually mount in boot2docker:

  1. There are various ways to log in, use "Show" in "Oracle VM VirtualBox Manager", or ssh/putty into docker by IP address 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>

But this is only good until you restart the machine, and then the mount is lost...

Adding an automount to boot2docker:

While logged into the machine

  1. Edit/create (as root) /mnt/sda1/var/lib/boot2docker/bootlocal.sh, sda1 may be different for you...
  2. Add

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

With these changes, you should have a new mount point. This is one of the few files I could find that is called on boot and is persistent. Until there is a better solution, this should work.


Old method: Less recommended, but left as an alternative

  • Edit (as root) /mnt/sda1/var/lib/boot2docker/profile, sda1 may be different for you...
  • Add

    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>
    

As a last resort, you can take the slightly more tedious alternative, and you can just modify the boot image.

  • git -c core.autocrlf=false clone https://github.com/boot2docker/boot2docker.git
  • cd boot2docker
  • git -c core.autocrlf=false checkout v1.8.1 #or your appropriate version
  • Edit rootfs/etc/rc.d/automount-shares
  • Add try_mount_share <local_dir> <mount_name> line right before fi at the end. For example

    try_mount_share /e e
    

    Just be sure not to set the to anything the os needs, like /bin, etc...

  • docker build -t boot2docker . #This will take about an hour the first time :(
  • docker run --rm boot2docker > boot2docker.iso
  • Backup the old boot2docker.iso and copy your new one in its place, in ~/.docker/machine/machines/

This does work, it's just long and complicated

docker version 1.8.1, docker-machine version 0.4.0

Fibrillation answered 15/8, 2015 at 23:30 Comment(7)
For anyone having problems with this, I'm pretty sure I had to make the local paths match the ones in the docker-machine. Also docker-compose seemed to succeed in mounting the volumes while regular docker didn't -- not sure why.Banquet
Created a script for the solution mentioned here. Works on latest docker 1.10 and docker-machine 0.6.0 gist.github.com/cristobal/fcb0987871d7e1f7449eSqueal
Different resources talk about using /mnt/sda1/var/lib/boot2docker/profile, can you explain why you switched to using /mnt/sda1/var/lib/boot2docker/bootlocal.sh? Also, striking through this much text doesn't contribute to the readability of your answer ;-)Whaler
@Whaler Point taken about my formatting :). I do not remember off hand why I suggest the bootlocal.sh method anymore. All I can say is it looks cleaner to just use a mount command like I did in bootlocal.sh than it does in the profile. Also, typically, I believe the profile could be run multiple times, and a mount only needs to be run once, so it makes more sense. But both can work.Fibrillation
LOVE IT! Thank you!Rex
The Add Virtual Machine Mount Point (part 1) is all you need to do in latest Docker Toolbox v18.09.3. And even this is not required if mount path on host machine is under C:\Users directory. See my answer below.Titleholder
@Fibrillation is it possible to manage ownership of specific shared subfolders? I have a problem with preparing setup of Postgres Docker container with persistent data. Changing ownership on nor host neither guest work. I could mount only Postgres data directory as shared with guest, but I would rather prefer to share entire project directory and mount its subdirectories freely with simple -v docker switch during my work.Ashcraft
L
28

Also ran into this issue and it looks like local volumes are not mounted when using docker-machine. A hack solution is to

  1. get the current working directory of the docker-machine instance docker-machine ssh <name> pwd

  2. use a command line tool like rsync to copy folder to remote system

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

The default pwd is /root so the command above would be rsync -avzhe ssh --progress <name_of_folder> username@remote_ip:/root

NB: you would need to supply the password for the remote system. You can quickly create one by ssh into the remote system and creating a password.

  1. change the volume mount point in your docker-compose.yml file from .:/app to /root/<name_of_folder>:/app

  2. run docker-compose up -d

NB when changes are made locally, don't forget to rerun rsync to push the changes to the remote system.

Its not perfect but it works. An issue is ongoing https://github.com/docker/machine/issues/179

Other project that attempt to solve this include docker-rsync

Lavernelaverock answered 28/5, 2015 at 16:32 Comment(8)
rsync needs to be installed on remote system it seems ` sh: rsync: not found rsync: connection unexpectedly closed (0 bytes received so far) [sender] rsync error: remote command not found (code 127) at /SourceCache/rsync/rsync-45/rsync/io.c(453) [sender=2.6.9] ` How did you get it to work?Stuff
rsync needs to be installed on your local systemLavernelaverock
Using these steps completely locks up my digitalocean host.. The files transfer over fine, but when I try to reconnect to the host with docker-machine, I get exit status 255 and have to completely recreate the machine.Linctus
Created a script for the solution mentioned here. Works on latest docker 1.10 and docker-machine 0.6.0 gist.github.com/cristobal/fcb0987871d7e1f7449eSqueal
@Squeal it looks like you scripted the mount solution, not the rsync solution?Fibrillation
Well the reason i created a mount solution, is due to how our stuff is setup internally at work . We have to mount 300GB+ volumes that contain DB files. This is some legacy stuff :/Squeal
It also seems that i posted the solution to the wrong thread here :PSqueal
What's the up-to-date answer here?Pouliot
P
14

At the moment I can't really see any way to mount volumes on machines, so the approach by now would be to somehow copy or sync the files you need into the machine.

There are conversations on how to solve this issue on the docker-machine's github repo. Someone made a pull request implementing scp on docker-machine and it's already merged on master, so it's very likely that the next release will include it.

Since it's not yet released, by now I would recommend that if you have your code hosted on github, just clone your repo before you run the app

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: Looking further I found that the feature is already available in the latest binaries, when you get them you'll be able to copy your local project running a command like this:

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

Being this the general form:

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

So you can copy files from, to and between machines.

Cheers!1

Ppi answered 7/6, 2015 at 0:52 Comment(2)
the documentation for docker-machine scp : docs.docker.com/machine/reference/scpExert
this method is very slow :(Elsaelsbeth
H
5

Since October 2017 there is a new command for docker-machine that does the trick, but make sure there is nothing in the directory before executing it, otherwise it might get lost:

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

Check the docs for more information: https://docs.docker.com/machine/reference/mount/

PR with the change: https://github.com/docker/machine/pull/4018

Highlander answered 13/2, 2018 at 23:23 Comment(3)
Just unbelievably, from the Docker Machine documentation (that you linked), it is - literally - impossible to know that the order in the command is ...:<guest-path> <host-path> (rather than the other way around). Something as simple and critical as that to note in documentation ... just isn't!Faydra
I guess it is not very explicit, you are right. It has to be guessed from the list of commandsHighlander
It does the trick, but in other way. It allows to mount docker-machine dir on your local machine. Unfortunately it doesn't allow other way :(Cudbear
C
4

If you choose the rsync option with docker-machine, you can combine it with the docker-machine ssh <machinename> command like this:

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

It uses this command format of rsync, leaving HOST blank:

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

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

Cabalism answered 18/7, 2016 at 23:18 Comment(0)
D
2

Finally figured out how to upgrade Windows Docker Toolbox to v1.12.5 and keep my volumes working by adding a shared folder in Oracle VM VirtualBox manager and disabling path conversion. If you have Windows 10+ then you're best to use the newer Docker for Windows.

1st the upgrade Pain:

  1. Uninstall VirtualBox first.
    • Yep that may break stuff in other tools like Android Studio. Thanks Docker :(
  2. Install new version of Docker Toolbox.

Redis Database Example: redis: image: redis:alpine container_name: redis ports: - "6379" volumes: - "/var/db/redis:/data:rw"

In Docker Quickstart Terminal ....

  1. run docker-machine stop default - Ensure VM is haulted

In Oracle VM VirtualBox Manager ...

  1. Added a shared folder in default VM via or command line
    • D:\Projects\MyProject\db => /var/db

In docker-compose.yml...

  1. Mapped redis volume as: "/var/db/redis:/data:rw"

In Docker Quickstart Terminal ....

  1. Set COMPOSE_CONVERT_WINDOWS_PATHS=0 (for Toolbox version >= 1.9.0)
  2. run docker-machine start default to restart the VM.
  3. cd D:\Projects\MyProject\
  4. docker-compose up should work now.

Now creates redis database in D:\Projects\MyProject\db\redis\dump.rdb

Why avoid relative host paths?

I avoided relative host paths for Windows Toolbox as they may introduce invalid '\' chars. It's not as nice as using paths relative to docker-compose.yml but at least my fellow developers can easily do it even if their project folder is elsewhere without having to hack the docker-compose.yml file (bad for SCM).

Original Issue

FYI ... Here is the original error I got when I used nice clean relative paths that used to work just fine for older versions. My volume mapping used to be just "./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

This breaks for two reasons ..

  1. It can't access D: drive
  2. Volume paths can't include \ characters
    • docker-compose adds them and then blames you for it !!
    • Use COMPOSE_CONVERT_WINDOWS_PATHS=0 to stop this nonsense.

I recommend documenting your additional VM shared folder mapping in your docker-compose.yml file as you may need to uninstall VirtualBox again and reset the shared folder and anyway your fellow devs will love you for it.

Doenitz answered 6/1, 2017 at 4:41 Comment(1)
you sir, are a fine personAbigail
T
1

All other answers were good for the time but now (Docker Toolbox v18.09.3) all works out of the box. You just need to add a shared folder into VirtualBox VM.

Docker Toolbox automatically adds C:\Users as shared folder /c/Users under virtual linux machine (using Virtual Box shared folders feature), so if your docker-compose.yml file is located somewhere under this path and you mount host machine's directories only under this path - all should work out of the box.

For example:

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

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

The . path will be automatically converted to absolute path C:\Users\username\my-project and then to /c/Users/username/my-project. And this is exactly how this path is seen from the point of view of linux virtual machine (you can check it: docker-machine ssh and then ls /c/Users/username/my-project). So, the final mount will be /c/Users/username/my-project:/app.

All works transparently for you.

But this doesn't work if your host mount path is not under C:\Users path. For example, if you put the same docker-compose.yml under D:\dev\my-project.

This can be fixed easily though.

  1. Stop the virtual machine (docker-machine stop).
  2. Open Virtual Box GUI, open Settings of Virtual Machine named default, open Shared Folders section and add the new shared folder:

    • Folder Path: D:\dev
    • Folder Name: d/dev

    Press OK twice and close Virtual Box GUI.

  3. Start the virtual machine (docker-machine start).

That's all. All paths of host machine under D:\dev should work now in docker-compose.yml mounts.

Titleholder answered 5/6, 2019 at 4:47 Comment(0)
C
1

It can be done witch combination of three tools: docker-machine mount, rsync, inotifywait

TL;DR

Script based on all below is here

Let's say you have your docker-compose.yml and run_web.sh in /home/jdcaballerov/web

  1. Mount directory on machine which has same path as you have it on your host docker-machine machine:/home/jdcaballerov/web /tmp/some_random_dir
  2. Synchronize mounted directory with dir on your host rsync -r /home/jdcaballerov/web /tmp/some_random_dir
  3. Synchronize on every change of files in your directory:

    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
    

BE AWARE - there are two directories which has same path - one is on your local (host) machine, second is on docker machine.

Cudbear answered 20/12, 2019 at 2:49 Comment(0)
C
0

I assume the run_web.sh file is in the same directory as your docker-compose.yml file. Then the command should be command: /app/run_web.sh.

Unless the Dockerfile (that you are not disclosing) takes care of putting the run_web.sh file into the Docker image.

Culpepper answered 4/5, 2015 at 22:10 Comment(5)
thanks for your answer. It is on the same directory. However I notice the volume is not being mounted. Files are not available, and thats the question. How to add them. The structure is similar to syncano.com/…Landgrabber
Make sure you have the latest versions of both docker and dicker-compose.Culpepper
docker: Docker version 1.6.0, build 4749651, docker-machine version 0.2.0 (8b9eaf2), docker-compose 1.2.0Landgrabber
Have you modified the Dockerfile from syncano.com/… in any way?Culpepper
Yes, I do add the code, create the directory. The trouble is that when docker-compose executes it overwrites the volume: volumes: - .:/app and leaves an empty directory. I commented volumes in compose and it works.Landgrabber
B
0

After summarize posts here, attached updated script, to create additional host mount point and automount when Virtualbox restart. The working environment brief as below: - 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'
Babin answered 29/6, 2016 at 23:52 Comment(0)
L
0

I am using docker-machine 0.12.2 with the virtualbox drive on my local machine. I found that there is a directory /hosthome/$(user name) from where you have access to local files.

Laws answered 18/10, 2017 at 6:40 Comment(0)
P
0

Just thought I'd mention I've been using 18.03.1-ce-win65 (17513) on Windows 10 and I noticed that if you've previously shared a drive and cached the credentials, once you change your password docker will start having the volumes mounted within containers as blank.

It gives no indication that what is actually happening is that it is now failing to access the shared with the old cached credentials. The solution in this scenario is to reset the credentials either through the UI (Settings->Shared drives) or to disable then renable drive sharing and enter the new password.

It would be useful if docker-compose gave an error in these situations.

Pentylenetetrazol answered 10/6, 2018 at 17:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.