Skip to content
This repository has been archived by the owner on Dec 1, 2018. It is now read-only.

Commit

Permalink
Merge branch 'windows'
Browse files Browse the repository at this point in the history
  • Loading branch information
Leonid Makarov committed Apr 9, 2015
2 parents 98373a7 + 02dd412 commit 976e279
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 67 deletions.
106 changes: 83 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,6 @@ Boot2docker Vagrant box for optimized Docker and Docker Compose use on Mac and W
This is a temporary solution to achive better performance with synced folders and docker data volumes on Mac and Windows.
The stock boot2docker currently mounts host volumes via the default VirtualBox Guest Additions (vboxfs) mode, which is terribly slow. Much better performance can be achieved with NFS, SMB or rsync.

Supports all [Synced Folder](http://docs.vagrantup.com/v2/synced-folders/) options provided by Vagrant:
- vboxfs - native VirtualBox method, cross-platform, convenient and reliable, terribly slow
- NFS - better performance and convenience for Mac
- SMB - better performance and convenience for Windows (on par with NFS on Mac)
- rsync - best performance, cross-platform, one-way only

<a name="requirements"></a>
## Requirements
1. [VirtualBox](https://www.virtualbox.org/) 4.3.20+
Expand All @@ -27,20 +21,21 @@ This installs the following prerequisites and dependencies: brew, cask, virtualb

### Manual installation (Windows)

**On Windows** Git Bash is the recommended option to run console commands. **It must be run as an administrator.**
**On Windows** Git Bash is the recommended option to run console commands.
If you are having any issues, please check if they can be reproduced in Git Bash.

1. Copy the Vagrantfile in this repo into your `<Projects>` (shared boo2docker VM for multiple projects, recommended) or `<Project>` (dedicated boot2docker VM) directory.
2. Launch Git Bash as administrator
3. cd to `</path/to/project>`, start the VM and log into it
1. Copy `Vagrantfile` and `vagrant.yml.dist` files from this repo into your `<Projects>` (shared boo2docker VM for multiple projects, recommended) or `<Project>` (dedicated boot2docker VM) directory.
2. Rename `vagrant.yml.dist` to `vagrant.yml`
3. Launch Git Bash
4. cd to `</path/to/project>`, start the VM and log into it

```
cd </path/to/project>
vagrant up
vagrant ssh
```
3. Verify installation (you are in the boot2docker VM at this point)
5. Verify installation (you are in the boot2docker VM at this point)
```
docker version
Expand All @@ -50,48 +45,113 @@ If you are having any issues, please check if they can be reproduced in Git Bash
<a name="synced-folders"></a>
## Synced Folders options
Follow the instructions in the Vagrantfile (**Synced folders configuration** section) to switch between different options.
This box supports all [Synced Folder](http://docs.vagrantup.com/v2/synced-folders/) options provided by Vagrant:
- vboxfs - native VirtualBox method, cross-platform, convenient and reliable, terribly slow
- NFS - better performance and convenience for Mac
- SMB - better performance and convenience for Windows (on par with NFS on Mac)
- rsync - best performance, cross-platform, one-way only
Follow the instructions in the `vagrant.yml` file to switch between different sync options.
The best balance between performance and convenience can be achieved with NFS on Mac (default) and SMB on Windows (not default).
WARNING:
Make sure only one is enabled at a time (nfs/smb, vboxfs, rsync).
If several synced folders options are enabled at the same time the last one takes precedence.
Additional steps are required to get SMB or rsync to work on Windows. [See below](#synced-folders-win).
<a name="synced-folders-mac"></a>
### Mac
On Mac NFS provides good performance and convenience. It is the default option configured in the Vagrantfile.
Option comparison for Mac Drupal developers (using `time drush si -y` as a test case):
- vboxfs: 6x (slowest)
- NFS: 1.3x
- rsync: 1x (fastest)
NFS provides good performance and convenience. It is the default and recommended option on Mac.
<a name="synced-folders-win"></a>
### Windows
On Windows SMB provides good performance and convenience. It is the default option configured in the Vagrantfile.
Option comparison for Windows Drupal developers (using `time drush si -y` as a test case):
- vboxfs: 5x (slowest)
- SMB: 2x
- rsync: 1x (fastest)
**SMB**
SMB provides good performance and convenience. It is the recommended option, but NOT the default one on Windows.
**Enabling SMB**
To use the SMB synced folder type:
1. Stop the VM with: `vagrant halt`
2. Choose `smb` as the sync type in the `vagrant.yml` file.
3. Launch Git Bash as an administrator
4. Start the VM: `vagrant up`
To use the SMB synced folder type the command prompt executing Vagrant must have administrative privileges.
This can be done by launching the Git Bash shell as an administrator, then do `vagrant up` there.
While using SMB you have to control Vagrant from an elevated (run as admin) Git Bash shell.
**rsync**
**Enabling rsync**
rsync is not natively available on Windows.
Git for Windows comes with Git Bash shell, which is based on [MinGW/MSYS](http://www.mingw.org/wiki/msys).
MSYS has a package for rsync, which can be installed and accessed via Git Bash.
Download and extract the content on this [archive](https://drive.google.com/open?id=0B130F0xKxOWCTUN1d3djZGZ0M2M&authuser=0) into the `bin` directory of your Git installation (e.g. `c:\Program Files (x86)\Git\bin\`).
To use rsync on Windows:
1. Download and extract the content on this [archive](https://drive.google.com/open?id=0B130F0xKxOWCTUN1d3djZGZ0M2M&authuser=0) into the `bin` directory of your Git installation (e.g. `c:\Program Files (x86)\Git\bin\`).
2. Choose `rsync` as the sync type in the `vagrant.yml` file.
3. Provide an explicit list of folders to sync in the `vagrant.yml` file (`folders` sequence).
4. Reload the VM: `vagrant reload`
**SMB2 (experimental option)**
This is an experimental option.
Compared to `smb`, `smb2` does not require running vagrant as admin, but requires initial manual setup:
1. Create a Windows user with a password (e.g. `vagrant:<password>`)
2. Share the `<Projects>` directory.
> The share name has to match the directory name.
> E.g. share `C:\Work\Projects` as `Projects`
3. Give the user created in step 1 full access to the share.
4. Update `vagrant.yml`:
> ...
> type: 'smb2'
> ...
> smb_username: '<username>'
> smb_password: '<password>'
> ...
5. Reload the VM (`vagrant reload`)
<a name="vm-settings"></a>
## VirtualBox VM settings
Open `vagrant.yml` file and edit respective values.
- `v.gui` - Set to `true` for debugging. This will unhide VM's primary console screen. Default: `false`.
- `v.memory` - Memory settings (MB). Default: `2048`.
- `v.cpus: 1` - number of virtual CPU cores. Default: `1`.
Please note, VirtualBox works much better with a single CPU in most cases, this it is not recommended to change the `v.cpus` value.
<a name="vm-network"></a>
## Network settings
The default box private network IP is `192.168.10.10`.
To map additional IP addresses for use with multiple projects open `vagrant.yml` and ucomment respective lines:
```yaml
hosts:
- ip: 192.168.10.11
- ip: 192.168.10.12
- ip: 192.168.10.13
```

Project specific `<IP>:<port>` mapping for containers is done in via docker-compose in `docker-compose.yml`

## Tips

### Automate DOCKER_HOST variable export

This is only necessary for manual instllations. Install script takes care of this for you.
This is only necessary for manual instllations. On Mac the [setup.sh](setup.sh) scripts takes care of this for you.

Add the following in your .bashrc, .zshrc, etc. file to automate the environment variable export:

Expand Down
135 changes: 91 additions & 44 deletions Vagrantfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,45 @@
# Vagrant should NOT be run as root (with sudo).
if Process.uid == 0 and !Vagrant::Util::Platform.windows?
puts "No `sudo vagrant ...` please. Vagrant should be run as a regular user to avoid issues."
exit

# Determine paths
vagrant_root = File.dirname(__FILE__) # Vagrantfile location
vagrant_mount = vagrant_root.gsub(/[a-zA-Z]:/, '') # Trim Windows drive letters
vagrant_folder = File.basename(vagrant_root) # Folder name only. Used as the SMB share name

# Use vagrant.yml for local VM configuration overrides.
require 'yaml'
if !File.exist?(vagrant_root + '/vagrant.yml')
raise 'Configuration file not found! Please copy vagrant.yml.dist to vagrant.yml and try again.'
end
vconfig = YAML::load_file(vagrant_root + '/vagrant.yml')

# Determine if we are on Windows host or not
is_windows = Vagrant::Util::Platform.windows?
if is_windows
require 'win32ole'
# Determine if Vagrant was launched from the elevated command prompt
running_as_admin = ((`reg query HKU\\S-1-5-19 2>&1` =~ /ERROR/).nil? && is_windows)

# Method to create a network share on Windows using elevated command prompt
def windows_net_share(share, path)
command = 'cmd.exe'
args = "/C net share #{share}=#{path} /grant:everyone,FULL || timeout 5"
puts args
shell = WIN32OLE.new('Shell.Application')
shell.ShellExecute(command, args, nil, 'runas')
end
else
# Determine if Vagrant was launched with sudo (as root).
running_as_root = (Process.uid == 0)
end

# Vagrant should NOT be run as root/admin.
if running_as_root
# || running_as_admin
raise "Vagrant should be run as a regular user to avoid issues."
end

######################################################################

# Vagrant Box Configuration #
Vagrant.require_version ">= 1.6.3"

Vagrant.configure("2") do |config|
Expand All @@ -15,62 +51,73 @@ Vagrant.configure("2") do |config|
## Network ##

# The default box private network IP is 192.168.10.10
# Uncomment lines below to map additional IP addresses for use with multiple projects.
# Project specific IP:port mapping for containers is done in via docker-compose (docker-compose.yml)
#config.vm.network "private_network", ip: "192.168.10.11"
#config.vm.network "private_network", ip: "192.168.10.12"
#config.vm.network "private_network", ip: "192.168.10.13"


# Vagrantfile location
vagrant_root = File.dirname(__FILE__)
# Trim Windows drive letters
vagrant_mount = vagrant_root.gsub(/[a-zA-Z]:/, '')
# Configure additional IP addresses in vagrant.yml
for host in vconfig['hosts'] do
config.vm.network "private_network", ip: host['ip']
end

####################################################################
## Synced folders configuration ##

# Windows
if Vagrant::Util::Platform.windows?
# Uncomment for better performance on Windows (mount via SMB).
# Requires Vagrant to be run with admin privileges.
# Will also prompt for the Windows username and password to access the share.
config.vm.synced_folder vagrant_root, vagrant_mount, type: "smb"

# Mac
else
# Uncomment for better performance on Mac (mount via NFS).
# See https://github.com/mitchellh/vagrant/issues/2304 for why NFS over TCP may be better than over UDP.
#config.vm.synced_folder vagrant_root, vagrant_root, type: "nfs", mount_options: ["nolock", "vers=3", "udp"]
config.vm.synced_folder vagrant_root, vagrant_mount, type: "nfs", mount_options: ["nolock", "vers=3", "tcp"]

# This uses uid and gid of the user that started vagrant.
synced_folders = vconfig['synced_folders']
# nfs: better performance on Mac
if synced_folders['type'] == "nfs" && !is_windows
config.vm.synced_folder vagrant_root, vagrant_mount,
type: "nfs",
mount_options: ["nolock", "vers=3", "tcp"]
config.nfs.map_uid = Process.uid
config.nfs.map_gid = Process.gid
# smb: better performance on Windows. Requires Vagrant to be run with admin privileges.
elsif synced_folders['type'] == "smb" && is_windows
config.vm.synced_folder vagrant_root, vagrant_mount,
type: "smb",
smb_username: synced_folders['smb_username'],
smb_password: synced_folders['smb_password']
# smb2: experimental, does not require running vagrant as admin, requires initial manual setup.
elsif synced_folders['type'] == "smb2" && is_windows
# Create the share on the Windows host
#windows_net_share vagrant_share, vagrant_root
#Mount the share in boot2docker
config.vm.provision "shell", run: "always" do |s|
s.inline = <<-SCRIPT
mkdir -p vagrant $2
mount -t cifs -o uid=`id -u docker`,gid=`id -g docker`,sec=ntlm,username=$3,pass=$4 //192.168.10.1/$1 $2
SCRIPT
s.args = "#{vagrant_folder} #{vagrant_mount} #{vconfig['synced_folders']['smb_username']} #{vconfig['synced_folders']['smb_password']}"
end
# rsync: the best performance, cross-platform platform, one-way only. Run `vagrant rsync-auto` to start auto sync.
elsif synced_folders['type'] == "rsync"
# Only sync explicitly listed folders.
if (synced_folders['folders']).nil?
puts "WARNING: 'folders' list cannot be empty when using 'rsync' sync type. Please check your vagrant.yml file."
else
for synced_folder in synced_folders['folders'] do
config.vm.synced_folder "#{vagrant_root}/#{synced_folder}", "#{vagrant_mount}/#{synced_folder}",
type: "rsync",
rsync__exclude: ".git/",
rsync__args: ["--verbose", "--archive", "--delete", "-z", "--chmod=ugo=rwX"]
end
end
# vboxfs: reliable, cross-platform and terribly slow performance
else
puts "WARNING: defaulting to the slowest sync option (vboxfs)"
config.vm.synced_folder vagrant_root, vagrant_mount
end

# Cross-platform: vboxfs
# Uncomment for reliable, cross-platform and terribly slow performance (using vboxfs)
#config.vm.synced_folder vagrant_root, vagrant_mount

# Cross-platform: rsync
# Uncomment for the best performance (using rsync). Run `vagrant rsync-auto` to start auto sync.
#config.vm.synced_folder vagrant_root, vagrant_mount, type: "rsync", rsync__exclude: ".git/"

####################################################################

# Make host SSH keys available to containers on /.ssh
if File.directory?(File.expand_path("~/.ssh"))
config.vm.synced_folder "~/.ssh", "/.ssh"
end

######################################################################

## VirtualBox VM settings

config.vm.provider "virtualbox" do |v|
#v.gui = true # Uncomment for debugging
v.name = File.basename(vagrant_root) + "_boot2docker" # VirtualBox VM name
v.cpus = 1 # CPU settings. VirtualBox works much better with a single CPU.
v.memory = 2048 # Memory settings.
v.gui = vconfig['v.gui'] # Set to true for debugging. Will unhide VM's primary console screen.
v.name = vagrant_folder + "_boot2docker" # VirtualBox VM name
v.cpus = vconfig['v.cpus'] # CPU settings. VirtualBox works much better with a single CPU.
v.memory = vconfig['v.memory'] # Memory settings.
end

## Provisioning scripts ##
Expand Down
4 changes: 4 additions & 0 deletions setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ brew install docker-compose
echo -e "${green}Downloading Vagrantfile into the current directory...${NC}"
curl -sO https://raw.githubusercontent.com/blinkreaction/boot2docker-vagrant/master/Vagrantfile

# Download and renaming vagrant.yml.dist
echo -e "${green}Downloading and renaming vagrant.yml.dist into the current directory...${NC}"
curl https://raw.githubusercontent.com/blinkreaction/boot2docker-vagrant/master/vagrant.yml.dist > vagrant.yml

# Start the boot2docker VM
echo -e "${green}Starting the boot2docker VM...${NC}"
vagrant up
Expand Down
33 changes: 33 additions & 0 deletions vagrant.yml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Sync folders configuration
synced_folders:
# nfs: better performance on Mac, recommended.
# smb: better performance on Windows. Requires Vagrant to be run with admin privileges.
# smb2: experimental, does not require running vagrant as admin, requires initial manual setup.
# rsync: the best performance, cross-platform platform, one-way only. Run `vagrant rsync-auto` to start auto sync.
# When using rsync sync type the "folders" list below is mandatory.
# vboxfs (or leave empty): best compatibility and ease of setup, but poor performance.
type: 'nfs'
# smb_user, smb_password - The username and password used for authentication to mount the SMB mount.
# This is usually your Windows username and password, unless you created a dedicated user for vagrant.
smb_username: ''
smb_password: ''
# List of folders to sync with rsync. These should be subfolder names within the <Projects> folder (e.g. "drupal7")
# Uncomment and add folders per the example below as neccessary.
folders:
#- "projectA" # rsync projectA folder
#- "projectB" # rsync projectB folder
#- "" # rsync the whole <Projects> folder. WARNING: don't do this if your <Projects> folder is big.

# VirtualBox VM settings
v.gui: false # Set to true for debugging. Will unhide VM's primary console screen.
v.memory: 2048 # Memory settings.
v.cpus: 1 # CPU settings. VirtualBox works much better with a single CPU.

# Network settings
# The default box private network IP is 192.168.10.10
# Uncomment lines below to map additional IP addresses for use with multiple projects.
# Project specific `<IP>:<port>` mapping for containers is done in via docker-compose in `docker-compose.yml`
hosts:
#- ip: 192.168.10.11
#- ip: 192.168.10.12
#- ip: 192.168.10.13

0 comments on commit 976e279

Please sign in to comment.