如何在docker机器中安装本地卷

时间:2015-05-04 21:58:47

标签: docker dockerfile docker-compose

我正在尝试使用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代码挂载本地卷的推荐策略?

12 个答案:

答案 0 :(得分:91)

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

我不知道docker 1.6,但在1.8中你 CAN 为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. 启动&#34; Oracle VM VirtualBox Manager&#34;
  2. 右键单击<machine name>(默认)
  3. 设置...
  4. 共享文件夹
  5. 右侧的文件夹+图标(添加分享)
  6. 文件夹路径:<host dir>(e:)
  7. 文件夹名称:<mount name>(e)
  8. 检查&#34;自动安装&#34;和#34;永久性&#34; (只读,如果你想......)(自动装载目前有点无意义......)
  9. 在boot2docker中安装(第2部分)

    在boot2docker中手动安装

    1. 有多种方法可以登录,使用&#34; Show&#34; in&#34; Oracle VM VirtualBox Manager&#34;或ssh / putty通过IP地址docker-machine ip default等进入docker ...
    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>
    4. 但是这只有在你重新启动机器,然后安装失败后才有用......

      将自动挂载添加到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>
        
      3. 通过这些更改,您应该有一个新的挂载点。这是我能找到的少数几个在启动时调用的文件之一,并且是持久的。在有更好的解决方案之前,这应该可行。

        旧方法:不太推荐,但作为替代

        • 编辑(以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>行。例如

          try_mount_share /e e
          

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

        • docker build -t boot2docker .#这将是第一次约一个小时:(
        • docker run --rm boot2docker > boot2docker.iso
        • 备份旧的boot2docker.iso并将其复制到原位,在〜/ .docker / machine / machines /

        这确实有效,它只是漫长而复杂的

        docker version 1.8.1,docker-machine version 0.4.0

答案 1 :(得分:26)

还遇到了这个问题,看起来使用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>.
    
  3. 默认的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

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

      它不完美,但它有效。问题仍然存在https://github.com/docker/machine/issues/179

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

答案 2 :(得分:14)

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

如何在docker-machine的github repo上解决这个问题有conversations。有人在docker-machine上实现pull request实施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

更新:进一步观察我发现该功能已在latest binaries中提供,当您获得它们时,您将能够复制运行如下命令的本地项目:

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

这是一般形式:

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

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

干杯!1

答案 3 :(得分: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

答案 4 :(得分:3)

自2017年10月起,有一个针对docker-machine的新命令可以完成这项工作,但确保在执行之前目录中没有任何内容,否则它可能会丢失:

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

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

PR的变化:https://github.com/docker/machine/pull/4018

答案 5 :(得分:1)

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

升级第一次痛苦:

  1. 首先卸载VirtualBox。
    • 是的,这可能会破坏Android Studio等其他工具的功能。谢谢Docker :(
  2. 安装新版本的Docker Toolbox。
  3. Redis数据库示例: redis: image: redis:alpine container_name: redis ports: - "6379" volumes: - "/var/db/redis:/data:rw"

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

    1. 运行docker-machine stop default - 确保VM受到攻击
    2. 在Oracle VM VirtualBox Manager中......

      1. default VM via或命令行中添加了共享文件夹
        • D:\Projects\MyProject\db =&gt; /var/db
      2. docker-compose.yml ...

        1. 将redis卷映射为:"/var/db/redis:/data:rw"
        2. 在Docker快速入门终端....

          1. 设置COMPOSE_CONVERT_WINDOWS_PATHS=0(对于Toolbox版本&gt; = 1.9.0)
          2. 运行docker-machine start default以重新启动VM。
          3. cd D:\Projects\MyProject\
          4. docker-compose up现在应该可以使用了。
          5. 现在在D:\Projects\MyProject\db\redis\dump.rdb

            中创建redis数据库

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

            避免使用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来阻止这种废话。
            3. 我建议您在docker-compose.yml文件中记录其他VM共享文件夹映射,因为您可能需要再次卸载VirtualBox并重置共享文件夹,无论如何,您的开发人员都会爱你。

答案 6 :(得分:0)

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

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

答案 7 :(得分: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'

答案 8 :(得分:0)

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

答案 9 :(得分:0)

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

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

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

答案 10 :(得分:0)

所有其他答案目前都很好,但是现在(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挂载中工作。

答案 11 :(得分:0)

可以结合三种工具来完成: docker-machine mountrsyncinotifywait

  

TL; DR

     

基于以下所有is here

的脚本

假设您在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上将挂载的目录与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计算机上。