├── LICENSE ├── README.md ├── docker-machine-nfs.sh └── readme_image.gif /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2007 Adlogix 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Docker Machine NFS 2 | 3 | ## Requirements 4 | 5 | * [Docker Machine](https://docs.docker.com/machine/) 0.5.0+ 6 | 7 | ## Mac OS X 10.9+ 8 | 9 | Activates [NFS](https://en.wikipedia.org/wiki/Network_File_System) for an 10 | existing boot2docker box created through 11 | [Docker Machine](https://docs.docker.com/machine/). 12 | 13 | :warning: There can be an issue with the NFS under Mac OS X High Sierra (see issue [#79](https://github.com/adlogix/docker-machine-nfs/issues/79) for more info) :warning: 14 | 15 | ## Windows 10 with WSL 16 | 17 | * [Install WSL](https://docs.microsoft.com/en-us/windows/wsl/install-win10) 18 | * [Install VirtualBox](https://www.virtualbox.org/wiki/Downloads) 19 | * [Setup Docker-machine for WSL](https://www.paraesthesia.com/archive/2018/09/20/docker-on-wsl-with-virtualbox-and-docker-machine/) 20 | * [Install haneWIN NFS server](https://hanewin.net/nfs-e.htm) 21 | * [Install `docker-machine-nfs`](#standalone) 22 | * Mount drives under root (e.g. `/c`) - [Can be configured in `/etc/wsl.conf` - `automount`](https://devblogs.microsoft.com/commandline/automatically-configuring-wsl/) 23 | * Tested with these attributes: `docker-machine-nfs MACHINE-NAME --shared-folder=/c/Users/ --mount-opts="rw,vers=3,tcp,nolock,noacl,async"` 24 | 25 | ## Install 26 | 27 | ### Standalone 28 | 29 | ```sh 30 | curl -s https://raw.githubusercontent.com/adlogix/docker-machine-nfs/master/docker-machine-nfs.sh | 31 | sudo tee /usr/local/bin/docker-machine-nfs > /dev/null && \ 32 | sudo chmod +x /usr/local/bin/docker-machine-nfs 33 | ``` 34 | 35 | ### [Homebrew](http://brew.sh/) 36 | 37 | ```sh 38 | brew install docker-machine-nfs 39 | ``` 40 | 41 | 42 | ## Supports 43 | 44 | * Virtualbox 45 | * Parallels 46 | * VMware Fusion 47 | * VMware Vsphere 48 | * Xhyve 49 | * Hyperkit 50 | 51 | ## Usage 52 | 53 | * Create `docker-machine` as usual 54 | * Run `docker-machine-nfs` 55 | 56 | ```sh 57 | 58 | 59 | ## . 60 | ## ## ## == _ _ _____ ____ 61 | ## ## ## ## ## === | \ | | ___/ ___| 62 | /"""""""""""""""""\___/ === | \| | |_ \___ \ 63 | ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ / ===- ~~~ | |\ | _| ___) | 64 | \______ o __/ |_| \_|_| |____/ 65 | \ \ __/ 66 | \____\_______/ 67 | 68 | 69 | Usage: $ docker-machine-nfs [options] 70 | 71 | Options: 72 | 73 | -f, --force Force reconfiguration of nfs 74 | -n, --nfs-config NFS configuration to use in /etc/exports. (default to '-alldirs -mapall=\$(id -u):\$(id -g)') 75 | -s, --shared-folder,... Folder to share (default to /Users) 76 | -m, --mount-opts NFS mount options (default to 'noacl,async') 77 | 78 | Examples: 79 | 80 | $ docker-machine-nfs test 81 | 82 | > Configure the /Users folder with NFS 83 | 84 | $ docker-machine-nfs test --shared-folder=/Users --shared-folder=/var/www 85 | 86 | > Configures the /Users and /var/www folder with NFS 87 | 88 | $ docker-machine-nfs test --shared-folder=/var/www --nfs-config="-alldirs -maproot=0" 89 | 90 | > Configure the /var/www folder with NFS and the options '-alldirs -maproot=0' 91 | 92 | $ docker-machine-nfs test --mount-opts="noacl,async,nolock,nfsvers=3,udp,noatime,actimeo=1" 93 | 94 | > Configure the /User folder with NFS and specific mount options. 95 | 96 | $ docker-machine-nfs test --ip 192.168.1.12 97 | 98 | > docker-machine will connect to your host machine via this address 99 | 100 | ``` 101 | 102 | ## Troubleshooting 103 | 104 | - **Failed to mount on WSL** 105 | ``` 106 | Allow following exe's in "Windows Firewall" or any other firewall software used 107 | Directory -- c:/Program Files/nfsd 108 | - pmapd.exe 109 | - nfssrv.exe 110 | - nfsd.exe 111 | ``` 112 | 113 | ## Credits 114 | 115 | * Heavily inspired by @[mattes](https://github.com/mattes) ruby version 116 | [boot2docker-nfs.rb](https://gist.github.com/mattes/4d7f435d759ca2581347). 117 | * @[DzeryCZ](https://github.com/DzeryCZ) added support for Windows with WSL 118 | -------------------------------------------------------------------------------- /docker-machine-nfs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # The MIT License (MIT) 4 | # Copyright © 2015 Toni Van de Voorde 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the “Software”), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | # 24 | 25 | set -o errexit 26 | 27 | # BEGIN _functions 28 | 29 | # @info: Prints the ascii logo 30 | asciiLogo () 31 | { 32 | echo 33 | echo 34 | echo ' ## .' 35 | echo ' ## ## ## == _ _ _____ ____' 36 | echo ' ## ## ## ## ## === | \ | | ___/ ___|' 37 | echo ' /"""""""""""""""""\___/ === | \| | |_ \___ \' 38 | echo ' ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ / ===- ~~~ | |\ | _| ___) |' 39 | echo ' \______ o __/ |_| \_|_| |____/' 40 | echo ' \ \ __/' 41 | echo ' \____\_______/' 42 | echo 43 | echo 44 | } 45 | 46 | # @info: Prints the usage 47 | usage () 48 | { 49 | 50 | asciiLogo 51 | 52 | cat < [options] 54 | 55 | Options: 56 | 57 | -f, --force Force reconfiguration of nfs 58 | -n, --nfs-config NFS configuration to use in /etc/exports. (default to '-alldirs -mapall=\$(id -u):\$(id -g)') 59 | -s, --shared-folder,... Folder to share (default to /Users) 60 | -m, --mount-opts NFS mount options (default to 'noacl,async,nfsvers=3') 61 | -i, --use-ip-range Changes the nfs export ip to a range (e.g. -network 192.168.99.100 becomes -network 192.168.99) 62 | -p, --ip Configures the docker-machine to connect to your host machine via a specific ip address 63 | -t, --timeout Configures how long the timeout should be for docker-machine commands 64 | 65 | Examples: 66 | 67 | $ docker-machine-nfs test 68 | 69 | > Configure the /Users folder with NFS 70 | 71 | $ docker-machine-nfs test --shared-folder=/Users --shared-folder=/var/www 72 | 73 | > Configures the /Users and /var/www folder with NFS 74 | 75 | $ docker-machine-nfs test --shared-folder=/var/www --nfs-config="-alldirs -maproot=0" 76 | 77 | > Configure the /var/www folder with NFS and the options '-alldirs -maproot=0' 78 | 79 | $ docker-machine-nfs test --mount-opts="noacl,async,nolock,nfsvers=3,udp,noatime,actimeo=1" 80 | 81 | > Configure the /User folder with NFS and specific mount options. 82 | 83 | $ docker-machine-nfs test --ip 192.168.1.12 84 | 85 | > docker-machine will connect to your host machine via this address 86 | EOF 87 | exit 0 88 | } 89 | 90 | # @info: Prints error messages 91 | # @args: error-message 92 | echoError () 93 | { 94 | printf "\033[0;31mFAIL\n\n$1 \033[0m\n" 95 | } 96 | 97 | # @info: Prints warning messages 98 | # @args: warning-message 99 | echoWarn () 100 | { 101 | printf "\033[0;33m$1 \033[0m\n" 102 | } 103 | 104 | # @info: Prints success messages 105 | # @args: success-message 106 | echoSuccess () 107 | { 108 | printf "\033[0;32m$1 \033[0m\n" 109 | } 110 | 111 | # @info: Prints check messages 112 | # @args: success-message 113 | echoInfo () 114 | { 115 | printf "\033[1;34m[INFO] \033[0m$1" 116 | } 117 | 118 | # @info: Prints property messages 119 | # @args: property-message 120 | echoProperties () 121 | { 122 | printf "\t\033[0;35m- $1 \033[0m\n" 123 | } 124 | 125 | # @info: Checks if a given property is set 126 | # @return: true, if variable is not set; else false 127 | isPropertyNotSet() 128 | { 129 | if [ -z ${1+x} ]; then return 0; else return 1; fi 130 | } 131 | 132 | # @info: Sets the default properties 133 | setPropDefaults() 134 | { 135 | prop_machine_name= 136 | prop_shared_folders=() 137 | prop_nfs_config="-alldirs -mapall="$(id -u):$(id -g) 138 | prop_mount_options="noacl,async,nfsvers=3" 139 | prop_force_configuration_nfs=false 140 | prop_use_ip_range=false 141 | prop_timeout= 142 | } 143 | 144 | # @info: Resolve APFS firmlinks to their actual location 145 | resolveHostPath() 146 | { 147 | firmlinked_dir="/System/Volumes/Data$1" 148 | if [ -d "$firmlinked_dir" ] ; then 149 | echo $firmlinked_dir 150 | else 151 | echo $1 152 | fi 153 | } 154 | 155 | # @info: Parses and validates the CLI arguments 156 | parseCli() 157 | { 158 | 159 | [ "$#" -ge 1 ] || usage 160 | 161 | prop_machine_name=$1 162 | 163 | for i in "${@:2}" 164 | do 165 | case $i in 166 | -s=*|--shared-folder=*) 167 | local shared_folder="${i#*=}" 168 | shift 169 | 170 | if [ ! -d "$shared_folder" ]; then 171 | echoError "Given shared folder '$shared_folder' does not exist!" 172 | exit 1 173 | fi 174 | 175 | prop_shared_folders+=("$shared_folder") 176 | ;; 177 | 178 | -n=*|--nfs-config=*) 179 | prop_nfs_config="${i#*=}" 180 | ;; 181 | 182 | -m=*|--mount-opts=*) 183 | prop_mount_options="${i#*=}" 184 | ;; 185 | 186 | -f|--force) 187 | prop_force_configuration_nfs=true 188 | ;; 189 | 190 | -i|--use-ip-range) 191 | prop_use_ip_range=true 192 | ;; 193 | 194 | -p=*|--ip=*) 195 | prop_use_ip="${i#*=}" 196 | ;; 197 | 198 | -t=*|--timeout=*) 199 | prop_timeout="-t ${i#*=}" 200 | ;; 201 | 202 | *) 203 | echoError "Unknown argument '$i' given" 204 | echo #EMPTY 205 | usage 206 | ;; 207 | esac 208 | done 209 | 210 | if [ "$(isWsl)" = "true" ]; then 211 | local default_shared_foder="/c/Users" 212 | else 213 | local default_shared_foder="/Users" 214 | fi 215 | 216 | if [ ${#prop_shared_folders[@]} -eq 0 ]; then 217 | prop_shared_folders+=("${default_shared_foder}") 218 | fi; 219 | 220 | echoInfo "Configuration:" 221 | 222 | echo #EMPTY 223 | echo #EMPTY 224 | 225 | echoProperties "Machine Name: $prop_machine_name" 226 | for shared_folder in "${prop_shared_folders[@]}" 227 | do 228 | echoProperties "Shared Folder: $shared_folder" 229 | done 230 | 231 | echoProperties "Mount Options: $prop_mount_options" 232 | echoProperties "Force: $prop_force_configuration_nfs" 233 | 234 | echo #EMPTY 235 | 236 | } 237 | 238 | # @info: Checks if the machine is present 239 | # @args: machine-name 240 | # @return: (none) 241 | checkMachinePresence () 242 | { 243 | echoInfo "machine presence ... \t\t\t" 244 | 245 | machine_name=$(docker-machine ls $2 --filter "Name=^$1$" -q) 246 | 247 | if [ "" = "${machine_name}" ]; then 248 | echoError "Could not find the machine '$1'!"; exit 1; 249 | fi 250 | 251 | echoSuccess "OK" 252 | } 253 | 254 | # @info: Checks if the machine is running 255 | # @args: machine-name 256 | # @return: (none) 257 | checkMachineRunning () 258 | { 259 | echoInfo "machine running ... \t\t\t" 260 | 261 | machine_state=$(docker-machine ls $2 --filter "Name=^$1$" --format "{{.State}}") 262 | 263 | if [ "Running" != "${machine_state}" ]; then 264 | echoError "The machine '$1' is not running but '${machine_state}'!"; 265 | exit 1; 266 | fi 267 | 268 | echoSuccess "OK" 269 | } 270 | 271 | # @info: Returns the driver used to create the machine 272 | # @args: machine-name 273 | # @return: The driver used to create the machine 274 | getMachineDriver () 275 | { 276 | docker-machine ls $2 --filter "Name=^$1$" --format "{{.DriverName}}" 277 | } 278 | 279 | # @info: Loads mandatory properties from the docker machine 280 | lookupMandatoryProperties () 281 | { 282 | echoInfo "Lookup mandatory properties ... \t\t" 283 | 284 | prop_machine_ip=$(docker-machine ip $1) 285 | 286 | prop_machine_driver=$(getMachineDriver $1 "$2") 287 | 288 | if [ "$prop_machine_driver" = "vmwarefusion" ] || [ "$prop_machine_driver" = "vmware" ]; then 289 | prop_network_id="Shared" 290 | prop_nfshost_ip=${prop_use_ip:-"$(ifconfig -m `route get $prop_machine_ip | awk '{if ($1 ~ /interface:/){print $2}}'` | awk 'sub(/inet /,""){print $1}')"} 291 | if [ "" = "${prop_nfshost_ip}" ]; then 292 | echoError "Could not find the vmware fusion net IP!"; exit 1 293 | fi 294 | local nfsd_line="nfs.server.mount.require_resv_port = 0" 295 | echoSuccess "\t\tOK" 296 | 297 | echoInfo "Check NFS config settings ... \n" 298 | if [ "$(cat /etc/nfs.conf | grep -c "$nfsd_line")" == "1" ]; then 299 | echoInfo "/etc/nfs.conf is setup correctly!" 300 | else 301 | echoWarn "\n !!! Sudo will be necessary for editing /etc/nfs.conf !!!" 302 | # Backup /etc/nfs.conf file 303 | sudo cp /etc/nfs.conf /etc/nfs.conf.bak && \ 304 | echo "nfs.server.mount.require_resv_port = 0" | \ 305 | sudo tee /etc/nfs.conf > /dev/null 306 | echoWarn "\n !!! Backed up /etc/nfs.conf to /nfs.conf.bak !!!" 307 | echoWarn "\n !!! Added 'nfs.server.mount.require_resv_port = 0' to /etc/nfs.conf !!!" 308 | fi 309 | echoSuccess "\n\t\t\t\t\t\tOK" 310 | return 311 | fi 312 | 313 | if [[ "$prop_machine_driver" =~ (xhyve|hyperkit|vmwarevsphere) ]]; then 314 | prop_network_id="Shared" 315 | prop_nfshost_ip=${prop_use_ip:-"$(ifconfig -m `route get $prop_machine_ip | awk '{if ($1 ~ /interface:/){print $2}}'` | awk 'sub(/inet /,""){print $1}')"} 316 | if [ "" = "${prop_nfshost_ip}" ]; then 317 | echoError "Could not find a route to the ${prop_machine_driver} docker-machine"; exit 1 318 | fi 319 | echoSuccess "OK" 320 | return 321 | fi 322 | 323 | if [ "$prop_machine_driver" = "parallels" ]; then 324 | prop_network_id="Shared" 325 | prop_nfshost_ip=${prop_use_ip:-"$(prlsrvctl net info \ 326 | ${prop_network_id} | grep 'IPv4 address' | sed 's/.*: //')"} 327 | 328 | if [ "" = "${prop_nfshost_ip}" ]; then 329 | echoError "Could not find the parallels net IP!"; exit 1 330 | fi 331 | 332 | echoSuccess "OK" 333 | return 334 | fi 335 | 336 | if [ "$prop_machine_driver" != "virtualbox" ]; then 337 | echoError "Unsupported docker-machine driver: $prop_machine_driver"; exit 1 338 | fi 339 | 340 | prop_network_id=$(VBoxManage showvminfo $1 --machinereadable | 341 | grep hostonlyadapter | cut -d'"' -f2) 342 | if [ "" = "${prop_network_id}" ]; then 343 | echoError "Could not find the virtualbox net name!"; exit 1 344 | fi 345 | 346 | prop_nfshost_ip=$(VBoxManage list hostonlyifs | tr -d '\r' | 347 | grep "${prop_network_id}$" -A 3 | grep IPAddress | 348 | cut -d ':' -f2 | xargs); 349 | if [ "" = "${prop_nfshost_ip}" ]; then 350 | echoError "Could not find the virtualbox net IP!"; exit 1 351 | fi 352 | 353 | echoSuccess "OK" 354 | } 355 | 356 | # @info: Configures the NFS 357 | configureNFSUnix() 358 | { 359 | echoInfo "Configure NFS ... \n" 360 | 361 | if isPropertyNotSet $prop_machine_ip; then 362 | echoError "'prop_machine_ip' not set!"; exit 1; 363 | fi 364 | 365 | echoWarn "\n !!! Sudo will be necessary for editing /etc/exports !!!" 366 | 367 | #-- Update the /etc/exports file and restart nfsd 368 | 369 | local exports_begin="# docker-machine-nfs-begin $prop_machine_name #" 370 | local exports_end="# docker-machine-nfs-end $prop_machine_name #" 371 | 372 | # Remove old docker-machine-nfs exports 373 | local exports=$(cat /etc/exports | \ 374 | tr "\n" "\r" | \ 375 | sed "s/${exports_begin}.*${exports_end}//" | \ 376 | tr "\r" "\n" 377 | ) 378 | 379 | # Write new exports blocks beginning 380 | exports="${exports}\n${exports_begin}\n" 381 | 382 | local machine_ip=$prop_machine_ip 383 | if [ "$prop_use_ip_range" = true ]; then 384 | machine_ip="-network ${machine_ip%.*}" 385 | fi 386 | 387 | for shared_folder in "${prop_shared_folders[@]}" 388 | do 389 | # Add new exports 390 | exports="${exports}\"$(resolveHostPath "$shared_folder")\" $machine_ip $prop_nfs_config\n" 391 | done 392 | 393 | # Write new exports block ending 394 | exports="${exports}${exports_end}" 395 | #Export to file 396 | printf "$exports" | sudo tee /etc/exports >/dev/null 397 | 398 | sudo nfsd restart ; sleep 2 && sudo nfsd checkexports 399 | 400 | echoSuccess "\t\t\t\t\t\tOK" 401 | } 402 | 403 | configureNFSWsl() 404 | { 405 | echoInfo "Configure NFS ... \n" 406 | 407 | local nfsdPath=$(sc.exe qc nfsserver | grep BINARY_PATH_NAME | awk '{split($0,a," : "); print a[2]}' | awk '{sub("nfsd.exe","",$0);}1' | awk '{sub("\\","/",$0);}1') 408 | local wslnfsdPath=$(wslpath -a "$nfsdPath" | tr -d '\r') 409 | wslnfsdPath+="exports" 410 | 411 | if [ ! -f "$wslnfsdPath" ]; then 412 | echoError "Configuration file was not found in $wslnfsdPath, please check installation of haneWin server" 413 | exit 1 414 | fi 415 | 416 | for shared_folder in "${prop_shared_folders[@]}" 417 | do 418 | local wsl_shared_folder=$(wslpath -w $shared_folder) 419 | echo "$wsl_shared_folder -alldirs -exec -mapall:1000,1000 #Added by docker-machine-nfs" >> "$wslnfsdPath" 420 | done 421 | 422 | echoProperties "$(net.exe stop nfsserver)" 423 | echoProperties "$(net.exe start nfsserver)" 424 | 425 | echoInfo "NFS server ... \t\t\t\t" 426 | echoSuccess "OK" 427 | } 428 | 429 | # @info: Configures the VirtualBox Docker Machine to mount nfs 430 | configureBoot2Docker() 431 | { 432 | echoInfo "Configure Docker Machine ... \t\t" 433 | 434 | if isPropertyNotSet $prop_machine_name; then 435 | echoError "'prop_machine_name' not set!"; exit 1; 436 | fi 437 | if isPropertyNotSet $prop_nfshost_ip; then 438 | echoError "'prop_nfshost_ip' not set!"; exit 1; 439 | fi 440 | 441 | # render bootlocal.sh and copy bootlocal.sh over to Docker Machine 442 | # (this will override an existing /var/lib/boot2docker/bootlocal.sh) 443 | 444 | local bootlocalsh="#!/bin/sh" 445 | 446 | if [ "$(isWsl)" = "true" ]; then 447 | bootlocalsh="${bootlocalsh} 448 | sudo umount /c/Users" 449 | else 450 | bootlocalsh="${bootlocalsh} 451 | sudo umount /Users" 452 | fi 453 | 454 | for shared_folder in "${prop_shared_folders[@]}" 455 | do 456 | bootlocalsh="${bootlocalsh} 457 | sudo mkdir -p \""$shared_folder"\"" 458 | done 459 | 460 | bootlocalsh="${bootlocalsh} 461 | sudo /usr/local/etc/init.d/nfs-client start" 462 | 463 | for shared_folder in "${prop_shared_folders[@]}" 464 | do 465 | bootlocalsh="${bootlocalsh} 466 | sudo mount -t nfs -o "$prop_mount_options" "$prop_nfshost_ip":\""$(resolveHostPath "$shared_folder")"\" \""$shared_folder"\"" 467 | done 468 | 469 | local file="/var/lib/boot2docker/bootlocal.sh" 470 | 471 | docker-machine ssh $prop_machine_name \ 472 | "echo '$bootlocalsh' | sudo tee $file && sudo chmod +x $file && sync" < /dev/null > /dev/null 473 | 474 | sleep 2 475 | 476 | echoSuccess "OK" 477 | } 478 | 479 | # @info: Restarts Docker Machine 480 | restartDockerMachine() 481 | { 482 | echoInfo "Restart Docker Machine ... \t\t" 483 | 484 | if isPropertyNotSet $prop_machine_name; then 485 | echoError "'prop_machine_name' not set!"; exit 1; 486 | fi 487 | 488 | docker-machine restart $prop_machine_name > /dev/null 489 | 490 | echoSuccess "OK" 491 | } 492 | 493 | # @return: 'true', if NFS is mounted; else 'false' 494 | isNFSMounted() 495 | { 496 | for shared_folder in "${prop_shared_folders[@]}" 497 | do 498 | local nfs_mount=$(docker-machine ssh $prop_machine_name "sudo mount" < /dev/null | 499 | grep "$prop_nfshost_ip:$(resolveHostPath "$shared_folder") on") 500 | if [ "" = "$nfs_mount" ]; then 501 | echo "false"; 502 | return; 503 | fi 504 | done 505 | 506 | echo "true" 507 | } 508 | 509 | # @info: Verifies that NFS is successfully mounted 510 | verifyNFSMount() 511 | { 512 | echoInfo "Verify NFS mount ... \t\t\t" 513 | 514 | local attempts=10 515 | 516 | while [ ! $attempts -eq 0 ]; do 517 | sleep 1 518 | [ "$(isNFSMounted)" = "true" ] && break 519 | attempts=$(($attempts-1)) 520 | done 521 | 522 | if [ $attempts -eq 0 ]; then 523 | echoError "Cannot detect the NFS mount :("; exit 1 524 | fi 525 | 526 | echoSuccess "OK" 527 | } 528 | 529 | # @info: Displays the finish message 530 | showFinish() 531 | { 532 | printf "\033[0;36m" 533 | echo "--------------------------------------------" 534 | echo 535 | echo " The docker-machine '$prop_machine_name'" 536 | echo " is now mounted with NFS!" 537 | echo 538 | echo " ENJOY high speed mounts :D" 539 | echo 540 | echo "--------------------------------------------" 541 | printf "\033[0m" 542 | } 543 | 544 | # WSL 545 | 546 | # @return: 'true', if platform is WSL; else 'false' 547 | isWsl() 548 | { 549 | if [ "$(uname -r | grep 'Microsoft')" != "" ]; then 550 | echo "true" 551 | else 552 | echo "false" 553 | fi 554 | } 555 | 556 | if [ "$(isWsl)" = "true" ]; then 557 | printf "\033[0;32mPlaform WSl detected\033[0m\n" 558 | 559 | # @info: translate docker-machine to .exe 560 | function docker-machine() 561 | { 562 | docker-machine.exe "$@" 563 | } 564 | export -f docker-machine 565 | fi 566 | 567 | # END _functions 568 | 569 | setPropDefaults 570 | 571 | parseCli "$@" 572 | 573 | checkMachinePresence $prop_machine_name "$prop_timeout" 574 | checkMachineRunning $prop_machine_name "$prop_timeout" 575 | 576 | lookupMandatoryProperties $prop_machine_name "$prop_timeout" 577 | 578 | if [ "$(isNFSMounted)" = "true" ] && [ "$prop_force_configuration_nfs" = "false" ]; then 579 | echoSuccess "\n NFS already mounted." ; showFinish ; exit 0 580 | fi 581 | 582 | echo #EMPTY LINE 583 | 584 | echoProperties "Machine IP: $prop_machine_ip" 585 | echoProperties "Network ID: $prop_network_id" 586 | echoProperties "NFSHost IP: $prop_nfshost_ip" 587 | 588 | echo #EMPTY LINE 589 | 590 | if [ "$(isWsl)" = "true" ]; then 591 | configureNFSWsl 592 | else 593 | configureNFSUnix 594 | fi 595 | 596 | configureBoot2Docker 597 | restartDockerMachine 598 | 599 | verifyNFSMount 600 | 601 | showFinish 602 | -------------------------------------------------------------------------------- /readme_image.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adlogix/docker-machine-nfs/701ddceaade22ef242baf88e9911b4d184b77a76/readme_image.gif --------------------------------------------------------------------------------