我正在尝试使用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代码挂载本地卷的推荐策略?
答案 0 :(得分:91)
Docker-machine自动挂载用户目录......但有时候这还不够。
我不知道docker 1.6,但在1.8中你 CAN 为docker-machine添加了一个额外的装载
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 :(不需要停止机器)
<machine name>
(默认)<host dir>
(e:)<mount name>
(e)在boot2docker中手动安装:
docker-machine ip default
等进入docker ... sudo mkdir -p <local_dir>
sudo mount -t vboxsf -o defaults,uid=`id -u docker`,gid=`id -g docker` <mount_name> <local_dir>
但是这只有在你重新启动机器,然后安装失败后才有用......
将自动挂载添加到boot2docker :
登录机器时
/mnt/sda1/var/lib/boot2docker/bootlocal.sh
,sda1可能与您有所不同...... 添加
mkdir -p <local_dir>
mount -t vboxsf -o defaults,uid=`id -u docker`,gid=`id -g docker` <mount_name> <local_dir>
通过这些更改,您应该有一个新的挂载点。这是我能找到的少数几个在启动时调用的文件之一,并且是持久的。在有更好的解决方案之前,这应该可行。
旧方法:不太推荐,但作为替代
/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
这确实有效,它只是漫长而复杂的
docker version 1.8.1,docker-machine version 0.4.0
答案 1 :(得分:26)
还遇到了这个问题,看起来使用docker-machine时没有挂载本地卷。黑客解决方案是
获取docker-machine实例的当前工作目录docker-machine ssh <name> pwd
使用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快速创建一个到远程系统并创建密码。
将docker-compose.yml
文件中的卷装入点从.:/app
更改为/root/<name_of_folder>:/app
运行docker-compose up -d
注意在本地进行更改时,请不要忘记重新运行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
答案 4 :(得分:3)
自2017年10月起,有一个针对docker-machine的新命令可以完成这项工作,但确保在执行之前目录中没有任何内容,否则它可能会丢失:
docker-machine mount <machine-name>:<guest-path> <host-path>
查看文档以获取更多信息:https://docs.docker.com/machine/reference/mount/
答案 5 :(得分:1)
最后想出了如何将Windows Docker Toolbox升级到v1.12.5并通过在Oracle VM VirtualBox
管理器中添加共享文件夹并禁用路径转换来保持我的卷正常工作。如果你有Windows 10+,那么你最好使用较新的Docker for Windows。
升级第一次痛苦:
Redis数据库示例:
redis:
image: redis:alpine
container_name: redis
ports:
- "6379"
volumes:
- "/var/db/redis:/data:rw"
在Docker快速入门终端....
docker-machine stop default
- 确保VM受到攻击在Oracle VM VirtualBox Manager中......
default
VM via或命令行中添加了共享文件夹
D:\Projects\MyProject\db
=&gt; /var/db
在docker-compose.yml
...
"/var/db/redis:/data:rw"
在Docker快速入门终端....
COMPOSE_CONVERT_WINDOWS_PATHS=0
(对于Toolbox版本&gt; = 1.9.0)docker-machine start default
以重新启动VM。cd D:\Projects\MyProject\
docker-compose up
现在应该可以使用了。 现在在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
这有两个原因......
D:
驱动器\
个字符
docker-compose
添加它们,然后责怪你! COMPOSE_CONVERT_WINDOWS_PATHS=0
来阻止这种废话。我建议您在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
下。
这很容易解决。
docker-machine stop
)。打开Virtual Box GUI,打开名为default
的虚拟机设置,打开Shared Folders
部分并添加新的共享文件夹:
D:\dev
d/dev
按两次OK
,然后关闭Virtual Box GUI。
docker-machine start
)。仅此而已。 D:\dev
下主机的所有路径现在应该在docker-compose.yml
挂载中工作。
答案 11 :(得分:0)
可以结合三种工具来完成:
docker-machine mount
,rsync
,inotifywait
TL; DR
基于以下所有is here
的脚本
假设您在docker-compose.yml
中有run_web.sh
和/home/jdcaballerov/web
docker-machine machine:/home/jdcaballerov/web /tmp/some_random_dir
上的相同的路径
rsync -r /home/jdcaballerov/web /tmp/some_random_dir
上将挂载的目录与dir同步同步目录中文件的每次更改:
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计算机上。