88

我正在尝试将 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:没有这样的文件或目录

本地卷未安装到远程计算机。使用 webapps 代码挂载本地卷的推荐策略是什么?

4

12 回答 12

94

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

我不知道 docker 1.6,但在 1.8 中,您可以向docker -machine 添加一个额外的挂载

添加虚拟机挂载点(第 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 管理器”
  2. 右键单击<machine name>(默认)
  3. 设置...
  4. 共享文件夹
  5. 右侧的文件夹+ 图标(添加共享)
  6. 文件夹路径:<host dir>(e:)
  7. 文件夹名称:<mount name>(e)
  8. 检查“自动安装”和“永久”(如果你想只读的话......)(自动安装目前有点毫无意义......)

在 boot2docker 中安装(第 2 部分)

在 boot2docker 中手动挂载

  1. 有多种登录方式,使用“Oracle VM VirtualBox Manager”中的“Show”,或通过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. 编辑/创建(以 root 身份)/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
    

    请确保不要将其设置为操作系统需要的任何内容,例如 /bin 等...

  • docker build -t boot2docker .#第一次大约需要一个小时 :(
  • docker run --rm boot2docker > boot2docker.iso
  • 备份旧的 bo​​ot2docker.iso 并在 ~/.docker/machine/machines/ 中复制新的

这确实有效,只是冗长而复杂

码头工人版本 1.8.1,码头机器版本 0.4.0

于 2015-08-15T23:30:17.643 回答
28

也遇到了这个问题,使用 docker-machine 时似乎没有安装本地卷。一个黑客解决方案是

  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>.
    

默认密码是 /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

于 2015-05-28T16:32:04.870 回答
14

目前我真的看不到任何在机器上安装卷的方法,所以现在的方法是以某种方式将你需要的文件复制或同步到机器中。

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

由于它还没有发布,现在我建议如果你的代码托管在 github 上,只需在运行应用程序之前克隆你的 repo

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

于 2015-06-07T00:52:44.107 回答
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

于 2018-02-13T23:23:18.963 回答
4

如果您选择 rsync 选项与 docker-machine,您可以将其与如下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 )

于 2016-07-18T23:18:48.833 回答
1

终于弄清楚了如何将 Windows Docker Toolbox 升级到 v1.12.5 并通过在Oracle VM VirtualBox管理器中添加共享文件夹并禁用路径转换来保持我的卷正常工作。如果你有 Windows 10+,那么你最好使用更新的 Docker for Windows。

第一次升级痛点:

  1. 首先卸载 VirtualBox。
    • 是的,这可能会破坏其他工具(如 Android Studio)中的内容。谢谢码头工人:(
  2. 安装新版本的 Docker 工具箱。

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

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

  1. 运行docker-machine stop default- 确保 VM 被拖运

在 Oracle VM VirtualBox 管理器中...

  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 Toolbox 的相对主机路径,因为它们可能会引入无效的 '\' 字符。它不如使用相对于的路径好,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阻止这种废话。

我建议在你的文件中记录你的额外 VM 共享文件夹映射,docker-compose.yml因为你可能需要再次卸载 VirtualBox 并重置共享文件夹,无论如何你的开发人员会喜欢你的。

于 2017-01-06T04:41:18.857 回答
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挂载中工作。

于 2019-06-05T04:47:21.250 回答
1

它可以通过三种工具的组合来完成: docker-machine mount, rsync,inotifywait

TL;博士

基于以下所有的脚本在这里

假设你有你的docker-compose.ymlrun_web.sh/home/jdcaballerov/web

  1. 在与主机上具有相同路径的机器上挂载目录docker-machine machine:/home/jdcaballerov/web /tmp/some_random_dir
  2. 将挂载的目录与主机上的 dir 同步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 机器上

于 2019-12-20T02:49:25.207 回答
0

我假设该run_web.sh文件与您的文件位于同一目录中docker-compose.yml。那么命令应该是command: /app/run_web.sh.

除非Dockerfile(您没有透露)负责将run_web.sh文件放入 Docker 映像中。

于 2015-05-04T22:10:15.030 回答
0

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

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

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

于 2018-06-10T17:36:38.347 回答
0

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

于 2017-10-18T06:40:11.530 回答
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'
于 2016-06-29T23:52:25.797 回答