如何在Docker机器中挂载本地卷


85

我正在尝试将docker-machine与docker-compose一起使用。文件docker-compose.yml的定义如下:

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

运行时docker-compose up -d一切顺利,直到尝试执行命令并产生错误为止:

无法启动容器b58e2dfa503b696417c1c3f49e2714086d4e9999bd71915a53502cb6ef43936d:[8]系统错误:exec:“ ./run_web.sh”:stat ./run_web.sh:无此类文件或目录

本地卷未安装到远程计算机上。建议使用Webapp的代码挂载本地卷的策略是什么?


项目和docker-compose.yml的结构类似于本教程syncano.com/…–
jdcaballerov

1
这应该在docker-compose文档中,作为对那些可能在本地开始使用compose的文档的有用提示。本来可以节省我数小时的WTF时间,试图弄清楚为什么我的文件路径错误或找不到。不,我只是觉得傻。
timbrown 2015年

Answers:


93

Docker-machine会自动挂载用户目录...但是有时候这还不够。

我不知道泊坞窗1.6,但在1.8你CAN添加一个额外的安装到泊坞窗机

添加虚拟机挂载点(第1部分)

CLI:(仅在机器停止时有效)

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

所以在Windows中的一个例子是

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

GUI:(不要求停止机器)

  1. 启动“ Oracle VM VirtualBox Manager”
  2. 右键单击<machine name>(默认)
  3. 设定...
  4. 共享文件夹
  5. 右侧的Folder +图标(添加共享)
  6. 资料夹路径:<host dir>(e :)
  7. 资料夹名称:<mount name>(e)
  8. 选中“自动安装”和“永久”(仅在需要时读取...)(自动安装当前毫无意义...)

在boot2docker中安装(第2部分)

手动安装在boot2docker中

  1. 有多种登录方式,可以使用“ Oracle VM VirtualBox Manager”中的“显示”,也可以通过IP地址通过ssh / putty进入dockerdocker-machine ip default等。
  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>

但这只有在重新启动机器后挂载丢失的情况下才是好...

向boot2docker添加自动挂载

登录机器

  1. 编辑/创建(以根用户身份)/mnt/sda1/var/lib/boot2docker/bootlocal.sh,sda1对您而言可能有所不同...
  2. mkdir -p <local_dir>
    mount -t vboxsf -o defaults,uid=`id -u docker`,gid=`id -g docker` <mount_name> <local_dir>
    

进行了这些更改之后,您应该有了一个新的挂载点。这是我可以找到的少数几个文件,它们在引导时被调用并且是持久的。除非有更好的解决方案,否则此方法将起作用。


旧方法:不建议使用,但可以选择

  • 编辑(以root用户身份)/mnt/sda1/var/lib/boot2docker/profile,sda1对您而言可能有所不同...
  • 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>
    

作为最后的选择,您可以选择稍微麻烦一些的替代方法,并且可以只修改启动映像。

  • git -c core.autocrlf=false clone https://github.com/boot2docker/boot2docker.git
  • cd boot2docker
  • git -c core.autocrlf=false checkout v1.8.1 #或您合适的版本
  • 编辑 rootfs/etc/rc.d/automount-shares
  • try_mount_share <local_dir> <mount_name>最后在fi之前添加一行。例如

    try_mount_share /e e
    

    只是请确保不要将os设置为os所需的任何值,例如/ bin等。

  • docker build -t boot2docker . #第一次会花一个小时:(
  • docker run --rm boot2docker > boot2docker.iso
  • 备份旧的boot2docker.iso并将新副本复制到〜/ .docker / machine / machines /中。

确实可行,只是冗长而复杂

docker版本1.8.1,docker-machine版本0.4.0


对于任何对此有疑问的人,我敢肯定我必须使本地路径与docker-machine中的路径匹配。此外,docker-compose似乎成功挂载了卷,而常规docker却没有-不知道为什么。
spieden

3
为此处提到的解决方案创建了一个脚本。在最新的码头工人1.10泊坞窗机0.6.0 gist.github.com/cristobal/fcb0987871d7e1f7449e工程
瓦尔

不同的资源谈论使用/mnt/sda1/var/lib/boot2docker/profile,您能解释一下为什么切换到使用/mnt/sda1/var/lib/boot2docker/bootlocal.sh吗?此外,删除大量文字并不能提高答案的可读性;-)
Forage

1
@Forage Point关于我的格式:)。我不记得为什么我会建议这种bootlocal.sh方法了。我能说的是,像bootlocal.sh在配置文件中一样,像我一样使用mount命令看起来更干净。而且,通常来说,我认为profile可以多次运行,而挂载只需要运行一次,因此更有意义。但是两者都可以。
安迪

爱它!谢谢!
Qorbani

28

也遇到了这个问题,使用docker-machine时似乎未挂载本地卷。hack解决方案是

  1. 获取docker-machine实例的当前工作目录 docker-machine ssh <name> pwd

  2. 使用命令行工具,例如rsync将文件夹复制到远程系统

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

默认的pwd是/ root,所以上面的命令是 rsync -avzhe ssh --progress <name_of_folder> username@remote_ip:/root

注意:您需要提供远程系统的密码。您可以通过ssh进入远程系统并创建密码来快速创建一个。

  1. docker-compose.yml文件中的卷挂载点从.:/app更改为/root/<name_of_folder>:/app

  2. docker-compose up -d

注意,在本地进行更改时,请不要忘记重新运行rsync以将更改推送到远程系统。

它并不完美,但可以正常工作。问题持续存在https://github.com/docker/machine/issues/179

尝试解决此问题的其他项目包括docker-rsync


rsync需要安装在远程系统上,看起来好像`sh:rsync:未找到rsync:连接意外关闭(到目前为止已收到0个字节)[发送方] rsync错误:在/ SourceCache / rsync / rsync找不到远程命令(代码127) -45 / rsync / io.c(453)[sender = 2.6.9]`您是如何工作的?
krinker 2015年

1
rsync需要安装在您的本地系统上
gbozee 2015年

使用这些步骤可以完全锁定我的digitalocean主机。文件可以正常传输,但是当我尝试使用docker-machine重新连接到主机时,我exit status 255必须完全重建机器。
dsifford,2016年

1
为此处提到的解决方案创建了一个脚本。适用于最新docker 1.10docker-machine 0.6.0 gist.github.com/cristobal/fcb0987871d7e1f7449e
瓦尔

@cristobal似乎是您编写了安装解决方案的脚本,而不是rsync解决方案的脚本?
安迪

14

目前,我还看不到在机器上挂载卷的任何方法,因此目前的方法是将所需的文件复制或同步到机器中。

在docker-machine的github repo上有关于如何解决此问题的对话。有人提出了实施SCP的请求在docker-machine上已经在master上合并,因此下一个版本很可能会包含它。

由于它尚未发布,所以现在我建议如果您将代码托管在github上,则在运行应用程序之前先克隆存储库

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

更新:进一步查找,我发现该功能已在最新的二进制文件中提供,当您获取它们时,您将能够运行以下命令来复制本地项目:

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

这是一般形式:

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

因此,您可以在机器之间,之间以及之间复制文件。

干杯!1



2
这个方法很慢:(
Sergej Jevsejev

5

自2017年10月以来,有一个用于docker-machine的新命令可以实现该功能,但在执行该目录之前请确保目录中没有任何内容,否则可能会丢失:

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

检查文档以获取更多信息:https : //docs.docker.com/machine/reference/mount/

公关更改:https : //github.com/docker/machine/pull/4018


1
令人难以置信的是,从Docker Machine文档(您链接过)中,实际上-不可能知道命令中的顺序是...:<guest-path> <host-path>(而不是相反)。就像在文档中要注意的那样简单而关键……不是!
Dan Nissenbaum

我想这不是很明确,你是对的。必须从命令列表中进行猜测
Jorge

它可以解决问题,但以其他方式。它允许在本地计算机上挂载docker-machine dir。不幸的是,它不允许其他方式:(
掠夺

4

如果在docker-machine中选择rsync选项,则可以将其与以下docker-machine ssh <machinename>命令结合使用:

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

它使用rsync的以下命令格式,HOST留空:

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

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


1

最后,通过在Oracle VM VirtualBox管理器中添加共享文件夹并禁用路径转换,了解了如何将Windows Docker Toolbox升级到v1.12.5并使我的卷正常工作。如果您使用Windows 10+,则最好使用Windows的较新Docker。

1st升级痛苦:

  1. 首先卸载VirtualBox。
    • 是的,可能会破坏其他工具,例如Android Studio。谢谢Docker :(
  2. 安装新版本的Docker Toolbox。

Redis数据库示例: redis: image: redis:alpine container_name: redis ports: - "6379" volumes: - "/var/db/redis:/data:rw"

在Docker快速入门终端....

  1. 运行docker-machine stop default-确保虚拟机受惊

在Oracle VM VirtualBox Manager中...

  1. default通过或命令行在VM中 添加了共享文件夹
    • D:\Projects\MyProject\db => /var/db

docker-compose.yml...

  1. 映射的redis量为: "/var/db/redis:/data:rw"

在Docker快速入门终端....

  1. 设置COMPOSE_CONVERT_WINDOWS_PATHS=0(对于工具箱版本> = 1.9.0)
  2. 运行docker-machine start default以重新启动VM。
  3. cd D:\Projects\MyProject\
  4. docker-compose up 应该现在工作。

现在在以下位置创建redis数据库 D:\Projects\MyProject\db\redis\dump.rdb

为什么要避免相对主机路径?

避免使用Windows工具箱的相对主机路径,因为它们可能会引入无效的'\'字符。它不像使用相对路径那样好,docker-compose.yml但是至少我的同伴开发人员可以轻松地做到这一点,即使他们的项目文件夹位于其他位置而不必修改docker-compose.yml文件(对于SCM来说也不好)。

原始发行

仅供参考...这是当我使用漂亮的干净相对路径(过去在旧版本中正常工作)时遇到的原始错误。我的体积映射过去只是"./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

这有两个原因..

  1. 它无法访问D:驱动器
  2. 卷路径不能包含\字符
    • docker-compose 添加他们,然后责怪你!
    • 使用COMPOSE_CONVERT_WINDOWS_PATHS=0制止这种废话。

我建议您在docker-compose.yml文件中记录其他VM共享文件夹映射,因为您可能需要再次卸载VirtualBox并重置共享文件夹,无论如何,您的同胞开发人员都会为此而爱上您。


先生,您好吗
AaronHS '19

1

所有其他答案在当时都是不错的选择,但现在(Docker Toolbox v18.09.3)都可以立即使用。您只需要在VirtualBox VM中添加一个共享文件夹即可。

Docker Toolbox会自动添加C:\Users/c/Users虚拟Linux机器下的共享文件夹(使用Virtual Box共享文件夹功能),因此,如果您的docker-compose.yml文件位于此路径下的某个位置,而您仅在此路径下挂载主机的目录,则所有文件都应开箱即用。

例如:

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

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

.路径将自动转换为绝对路径C:\Users\username\my-project,然后转换为/c/Users/username/my-project。从linux虚拟机的角度来看,这就是这种路径的样子(您可以先检查docker-machine ssh,然后检查ls /c/Users/username/my-project)。因此,最终的坐骑将是/c/Users/username/my-project:/app

一切对您透明。

但是,如果主机安装路径不在C:\Users路径下,则此方法将无效。例如,如果将相同的内容docker-compose.yml放在下D:\dev\my-project

这可以很容易地解决。

  1. 停止虚拟机(docker-machine stop)。
  2. 打开Virtual Box GUI,打开名为的虚拟机设置default,打开Shared Folders部分并添加新的共享文件夹:

    • 资料夹路径: D:\dev
    • 文件夹名称: d/dev

    OK两次,然后关闭Virtual Box GUI。

  3. 启动虚拟机(docker-machine start)。

就这样。主机下的所有路径D:\dev现在应该可以在docker-compose.yml安装中使用。


1

它可以是三个工具完成的女巫组合: docker-machine mountrsyncinotifywait

TL; DR

基于下面所有内容的脚本在这里

比方说,你有你的docker-compose.yml,并run_web.sh/home/jdcaballerov/web

  1. 在与主机上具有相同路径的机器上挂载目录docker-machine machine:/home/jdcaballerov/web /tmp/some_random_dir
  2. 将安装的目录与主机上的目录同步 rsync -r /home/jdcaballerov/web /tmp/some_random_dir
  3. 同步目录中文件的每次更改:

    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
    

请注意-有两个目录具有相同的路径-一个目录在本地(主机)计算机上,第二个目录在docker计算机上。


0

我认为该run_web.sh文件与您的docker-compose.yml文件位于同一目录中。然后,命令应为command: /app/run_web.sh

除非Dockerfile(您未公开)负责将run_web.sh文件放入Docker映像。


感谢您的回答。它在同一目录中。但是,我注意到该卷尚未安装。文件不可用,这就是问题所在。如何添加它们。结构类似于syncano.com/…–
jdcaballerov

确保您拥有docker和Dicker-compose的最新版本。
Thomasleveil 2015年

docker:Docker版本1.6.0,内部版本4749651,docker机器版本0.2.0(8b9eaf2),docker-compose 1.2.0
jdcaballerov 2015年

您是否以任何方式从syncano.com/…修改了Dockerfile ?
Thomasleveil 2015年

1
是的,我确实添加了代码,创建了目录。问题在于,当docker-compose执行时,它会覆盖volume:volume:-。:/ app并留下一个空目录。我评论了compose中的卷,它起作用了。
jdcaballerov

0

在此处总结文章后,附上更新的脚本,以在Virtualbox重新启动时创建其他主机安装点并自动安装。工作环境简介如下:-Windows 7-docker-machine.exe版本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

我在本地计算机上将docker-machine 0.12.2与virtualbox驱动器一起使用。我发现有一个目录/hosthome/$(user name),您可以从中访问本地文件。


0

只是以为我提到我已经在Windows 10上使用18.03.1-ce-win65(17513),我注意到,如果您以前共享驱动器并缓存了凭据,则一旦更改密码,泊坞窗就会开始具有安装在容器中的卷为空白。

它没有迹象表明实际发生的事情是它现在无法使用旧的缓存凭据访问共享。在这种情况下,解决方案是通过UI(设置->共享驱动器)重置凭据,或者禁用然后启用驱动器共享并输入新密码。

如果docker-compose在这些情况下给出错误,将很有用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.