Docker Toolbox创建虚拟机时 --virtualbox-share-folder 共享目录参数的正确用法
参数用途:
在使用docker-machine 创建虚拟机时,带上参数 --virtualbox-share-folder,实现宿主机和虚拟机之间共享目录,进而实现宿主机、虚拟机、容器三者之间共享目录。比如,将Windows7上的网站页面文件放到C:\www目录下,创建虚机,启动httpd容器,发布一个Web网站。在Windows7上更新网站页面后,自动更新网站的内容。DockerToolbox的版本必须要17.05.0版本以后才行,字符串中两个冒号的Bug在machine 0.10版中才得到修复。
正确用法:
docker-machine create \
-d virtualbox \
--virtualbox-share-folder "c:\www:c/www" \
test
相关说明:
1、默认不带参数时,宿主机会自动将c:\Users目录共享到虚拟机的/c/Users目录。
2、使用该参数后,默认共享被替换,最终虚拟机只有一个/c/www共享目录。
3、虚拟机运行容器时,加上-v /c/www:/www,即可将宿主机的目录挂载到容器中。
4、如需要使用多个目录,可以使用vboxmanager.exe 程序实现自动创建。
5、字符串中两个冒号导致的问题(盘符冒号和分隔符冒号没有得到很好处理)在0.10版的machine中得到修复,(2017年2月27日).我使用的Dockertoolbox 17.03.0版本,刚刚发布,内置的machine 还是0.9版的,bug依然存在,后来更换17.05.0版本后,内置的machine 是0.11版本的,问题已经得到修复。
https://github.com/docker/machine/blob/457c02d06a155827c1c4af9b5ab38c0b6b4e48ea/CHANGELOG.md
踩坑过程:
1、在创建虚拟机的命令中,尝试了以下字符串,由于我使用的Dockertoolbox是17.03.0,内置的machine 版本是0.9版,存在Bug,所有无论怎么尝试,都没成功。
"c:\www:/www"
"\\?\c:\html:html"
"html:\\\\?\\c"
"\\\\?\\c:\\html:html"
"c/html:\\\\?\\c"
"\\\\?\\c:c:rw"
"\\\\?\\c:c"
"\\\\?\\c::c"
"/c:c"
"/c/html:c/html"
2、获取宿主机路径和虚拟机共享名的函数,第94行:
https://github.com/docker/machine/blob/e1a03348ad83d8e8adb19d696bc7bcfb18ccd770/drivers/virtualbox/virtualbox_windows.go#L94
func getShareDriveAndName() (string, string) {
return "c/Users", "\\\\?\\c:\\Users"
}
3、虚拟机共享目录和宿主机共享路径的获取函数代码段,第453行:
https://github.com/docker/machine/blob/master/drivers/virtualbox/virtualbox.go#L453
shareName, shareDir := getShareDriveAndName()
4、对字符串中两个冒号进行处理的函数代码位置(virtualbox.go中的第486行):
https://github.com/docker/machine/blob/master/drivers/virtualbox/virtualbox.go#L486
func parseShareFolder(shareFolder string) (string, string) {
split := strings.Split(shareFolder, ":")
shareDir := strings.Join(split[:len(split)-1], ":")
shareName := split[len(split)-1]
return shareDir, shareName
}
5、相关代码段:
shareName, shareDir := getShareDriveAndName() |
|
|
|
|
if d.ShareFolder != "" { |
|
shareDir, shareName = parseShareFolder(d.ShareFolder) |
|
} |
|
|
|
if shareDir != "" && !d.NoShare { |
|
log.Debugf("setting up shareDir '%s' -> '%s'", shareDir, shareName) |
|
if _, err := os.Stat(shareDir); err != nil && !os.IsNotExist(err) { |
|
return err |
|
} else if !os.IsNotExist(err) { |
|
if shareName == "" { |
|
// parts of the VBox internal code are buggy with share names that start with "/" |
|
shareName = strings.TrimLeft(shareDir, "/") |
|
// TODO do some basic Windows -> MSYS path conversion |
|
// ie, s!^([a-z]+):[/\\]+!\1/!; s!\\!/!g |
|
} |
|
|
|
// woo, shareDir exists! let's carry on! |
|
if err := d.vbm("sharedfolder", "add", d.MachineName, "--name", shareName, "--hostpath", shareDir, "--automount"); err != nil { |
|
return err |
|
} |
|
|
|
// enable symlinks |
|
if err := d.vbm("setextradata", d.MachineName, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/"+shareName, "1"); err != nil { |
|
return err |
|
} |
|
} |
|
} |
func parseShareFolder(shareFolder string) (string, string) { |
|
|
split := strings.Split(shareFolder, ":") |
|
shareDir := strings.Join(split[:len(split)-1], ":") |
|
shareName := split[len(split)-1] |
|
return shareDir, shareName |
|
} |