Last active
May 8, 2016 10:42
-
-
Save koemeet/fa4a777dea2e882c859d to your computer and use it in GitHub Desktop.
Vagrant setup for docker (Mac + Win supported)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
app: | |
build: . | |
ports: | |
- "80" | |
volumes: | |
- .:/var/www/html | |
environment: | |
- VIRTUAL_HOST=sylius.dev | |
elasticsearch: | |
image: elasticsearch:1.7 | |
ports: | |
- "9200:9200" | |
db: | |
image: mysql | |
ports: | |
- "3306:3306" | |
environment: | |
- MYSQL_ROOT_PASSWORD=root | |
jackrabbit: | |
image: steffenbrem/jackrabbit | |
ports: | |
- "8080:8080" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Sync folders configuration | |
synced_folders: | |
# vboxsf - native VirtualBox method, cross-platform, convenient and reliable, terribly slow | |
# nfs: better performance and convenience on Mac | |
# nfs2: optimized nfs settings, experimental (default on Mac) | |
# smb: better performance and convenience on Windows. Requires Vagrant to be run with admin privileges (not recommended). | |
# smb2: does not require running vagrant as admin (default on Windows). | |
# rsync: best performance, cross-platform platform, one-way only | |
# Run `vagrant rsync-auto` to start auto sync. | |
# When using rsync sync type the "rsync_folders" list below is mandatory. | |
# vboxsf: best compatibility and ease of setup, but poor performance. | |
# default: defaults to nfs2 on Mac and smb2 on Windows. | |
# '': disable synced folders. Useful in case you want to use 'individual_mounts' option below. | |
type: 'default' | |
# 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. | |
# If using the 'smb2' type above the user and share will be configured automatically. | |
smb_username: 'vagrant' | |
smb_password: 'vagrant' | |
# Create smb share on vagrant up (if type smb2). Set to false if you want to or already created the user and the smb share manually. | |
# If false, the share name should be equal to the directory name in which Vagrantfile is located. | |
smb2_auto: true | |
# 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. | |
# Note: you'll have to run `vagrant rsync-auto` in the background to keep the files in sync as you make changes | |
rsync_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. | |
# Coalescing threshold in seconds for https://github.com/smerrill/vagrant-gatling-rsync | |
rsync_latency: 0.5 | |
# Start rsync-auto automatically (Mac only for now) | |
rsync_auto: true | |
# Patterns excluded from rsync. Passed as --exclude <pattern> to rsync. | |
rsync_exclude: | |
- ".git/" | |
#- "files/" | |
# List of folders to mount individually. This is really only needed in the case where you want a container to write | |
# something back to the Host OS. If that describes your situation, use type = vboxsf. If you just want more control | |
# over what's mounted, go with type = nfs, which is much faster. | |
individual_mounts: | |
#- location: './logs' | |
# mount: '/home/docker/logs' | |
# type: 'vboxsf' | |
# options: 'uid=501,gid=20' | |
#- location: './logs' | |
# mount: '/home/docker/logs' | |
# type: 'nfs' | |
# options: 'nolock,vers=3,tcp' | |
# 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 | |
ip: | |
# The default box private network IP is 192.168.10.10 | |
primary: 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` | |
additional: | |
#- 192.168.10.11 | |
#- 192.168.10.12 | |
#- 192.168.10.13 | |
# Registry authentication. If your machine uses a private image, you must log in | |
# to the registry before running docker-machine up. This is especially useful | |
# when combined with compose_autostart: true. | |
docker_registry_auth: false | |
# Automatically start containers if docker-compose.yml is present in the current directory (default: false). | |
compose_autostart: false | |
# vhost-proxy (optional, enabled) | |
# Use a reverse proxy to map host name to containers. | |
# This is an alternative to using dedicated IP addresses in the 'hosts' section above. | |
# Containers must define a "VIRTUAL_HOST" environment variable to be recognized and routed by the vhost-proxy. | |
vhost_proxy: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# UI Object for console interactions. | |
@ui = Vagrant::UI::Colored.new | |
# Install required plugins if not present. | |
required_plugins = ["vagrant-triggers", "vagrant-gatling-rsync"] | |
required_plugins.each do |plugin| | |
need_restart = false | |
unless Vagrant.has_plugin? plugin | |
system "vagrant plugin install #{plugin}" | |
need_restart = true | |
end | |
exec "vagrant #{ARGV.join(' ')}" if need_restart | |
end | |
# Determine if we are on Windows host or not. | |
is_windows = Vagrant::Util::Platform.windows? | |
# Determine paths. | |
vagrant_root = File.dirname(__FILE__) # Vagrantfile location | |
if is_windows | |
vagrant_mount_point = `cygpath #{vagrant_root}`.strip! # Remove trailing \n | |
vagrant_mount_point = vagrant_mount_point.gsub(/\/cygdrive/, '') # Remove '/cygdrive' prefix | |
else | |
vagrant_mount_point = vagrant_root | |
end | |
vagrant_folder_name = 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') | |
@ui.error 'Configuration file not found! Please copy vagrant.yml.dist to vagrant.yml and try again.' | |
exit | |
end | |
$vconfig = YAML::load_file(vagrant_root + '/vagrant.yml') | |
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) | |
# Run command in an elevated shell. | |
def windows_elevated_shell(args) | |
command = 'cmd.exe' | |
args = "/C #{args} || timeout 10" | |
shell = WIN32OLE.new('Shell.Application') | |
shell.ShellExecute(command, args, nil, 'runas') | |
end | |
# Method to create the user and SMB network share on Windows. | |
def windows_net_share(share_name, path) | |
# Add the vagrant user if it does not exist. | |
smb_username = $vconfig['synced_folders']['smb_username'] | |
smb_password = $vconfig['synced_folders']['smb_password'] | |
command_user = "net user #{smb_username} || ( net user #{smb_username} #{smb_password} /add && WMIC USERACCOUNT WHERE \"Name='vagrant'\" SET PasswordExpires=FALSE )" | |
@ui.info "Adding vagrant user" | |
windows_elevated_shell command_user | |
# Add the SMB share if it does not exist. | |
command_share = "net share #{share_name} || net share #{share_name}=#{path} /grant:#{smb_username},FULL" | |
@ui.info "Adding vagrant SMB share" | |
windows_elevated_shell command_share | |
# Set folder permissions. | |
command_permissions = "icacls #{path} /grant #{smb_username}:(OI)(CI)M" | |
@ui.info "Setting folder permissions" | |
windows_elevated_shell command_permissions | |
end | |
# Method to remove the user and SMB network share on Windows. | |
def windows_net_share_remove(share_name) | |
smb_username = $vconfig['synced_folders']['smb_username'] | |
command_user = "net user #{smb_username} /delete || echo 'User #{smb_username} does not exist' && timeout 10" | |
windows_elevated_shell command_user | |
command_share = "net share #{share_name} /delete || echo 'Share #{share_name} does not exist' && timeout 10" | |
windows_elevated_shell command_share | |
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 | |
@ui.error "Vagrant should be run as a regular user to avoid issues." | |
exit | |
end | |
###################################################################### | |
# Vagrant Box Configuration # | |
Vagrant.require_version ">= 1.7.3" | |
Vagrant.configure("2") do |config| | |
config.vm.define "boot2docker" | |
config.vm.box = "blinkreaction/boot2docker" | |
config.vm.box_version = "1.9.0" | |
config.vm.box_check_update = true | |
## Network ## | |
box_ip = $vconfig['ip']['primary'] # e.g. 192.168.10.10 | |
host_ip = box_ip.gsub(/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/, '\1.\2.\3.1') # e.g. 192.168.10.1 | |
# Primary private network IP (default: 192.168.10.10) | |
# Using Intel PRO/1000 MT Desktop [82540EM] network adapter - shows slightly better performance compared to "virtio". | |
config.vm.network "private_network", ip: box_ip, nic_type: "82540EM" | |
# Addtional IP addresses (see vagrant.yml) | |
$vconfig['ip']['additional'].each do |private_ip| | |
config.vm.network "private_network", ip: private_ip, nic_type: "82540EM" | |
end unless $vconfig['ip']['additional'].nil? | |
#################################################################### | |
## Synced folders configuration ## | |
synced_folders = $vconfig['synced_folders'] | |
# nfs: Better performance on Mac | |
if synced_folders['type'] == "nfs" && !is_windows | |
@ui.success "Using nfs synced folder option" | |
config.vm.synced_folder vagrant_root, vagrant_mount_point, | |
type: "nfs", | |
mount_options: ["nolock", "vers=3", "tcp"] | |
config.nfs.map_uid = Process.uid | |
config.nfs.map_gid = Process.gid | |
# nfs2: Optimized NFS settings for even better performance on Mac, experimental | |
elsif ( synced_folders['type'] == "nfs2" || synced_folders['type'] == "default" ) && !is_windows | |
@ui.success "Using nfs2 synced folder option" | |
config.vm.synced_folder vagrant_root, vagrant_mount_point, | |
type: "nfs", | |
mount_options: ["nolock", "noacl", "nocto", "noatime", "nodiratime", "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 | |
@ui.success "Using smb synced folder option" | |
config.vm.synced_folder vagrant_root, vagrant_mount_point, | |
type: "smb", | |
smb_username: synced_folders['smb_username'], | |
smb_password: synced_folders['smb_password'] | |
# smb2: Better performance on Windows. Does not require running vagrant as admin. | |
elsif ( synced_folders['type'] == "smb2" || synced_folders['type'] == "default" ) && is_windows | |
@ui.success "Using smb2 synced folder option" | |
if $vconfig['synced_folders']['smb2_auto'] | |
# Create the share before 'up'. | |
config.trigger.before :up, :stdout => true, :force => true do | |
info 'Setting up SMB user and share' | |
windows_net_share vagrant_folder_name, vagrant_root | |
end | |
# Remove the share after 'halt'. | |
config.trigger.after :destroy, :stdout => true, :force => true do | |
info 'Removing SMB user and share' | |
windows_net_share_remove vagrant_folder_name | |
end | |
end | |
# 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,dir_mode=0777,file_mode=0777 //$5/$1 $2 | |
SCRIPT | |
s.args = "#{vagrant_folder_name} #{vagrant_mount_point} #{$vconfig['synced_folders']['smb_username']} #{$vconfig['synced_folders']['smb_password']} #{host_ip}" | |
end | |
# rsync: the best performance, cross-platform platform, one-way only. | |
elsif synced_folders['type'] == "rsync" | |
@ui.success "Using rsync synced folder option" | |
# Construct and array for rsync_exclude | |
rsync_exclude = [] | |
unless synced_folders['rsync_exclude'].nil? | |
for item in synced_folders['rsync_exclude'] do | |
rsync_exclude.push(item) | |
end | |
end | |
# Only sync explicitly listed folders. | |
if synced_folders['rsync_folders'].nil? | |
@ui.error "ERROR: 'folders' list cannot be empty when using 'rsync' sync type. Please check your vagrant.yml file." | |
exit | |
else | |
for synced_folder in synced_folders['rsync_folders'] do | |
config.vm.synced_folder "#{vagrant_root}/#{synced_folder}", "#{vagrant_mount_point}/#{synced_folder}", | |
type: "rsync", | |
rsync__exclude: rsync_exclude, | |
rsync__args: ["--archive", "--delete", "--compress", "--whole-file"] | |
end | |
end | |
# Configure vagrant-gatling-rsync | |
config.gatling.rsync_on_startup = false | |
config.gatling.latency = synced_folders['rsync_latency'] | |
config.gatling.time_format = "%H:%M:%S" | |
# Launch gatling-rsync-auto in the background | |
if synced_folders['rsync_auto'] && !is_windows | |
[:up, :reload, :resume].each do |trigger| | |
config.trigger.after trigger do | |
success "Starting background rsync-auto process..." | |
info "Run 'tail -f #{vagrant_root}/rsync.log' to see rsync-auto logs." | |
# Kill the old sync process | |
`kill $(pgrep -f rsync-auto) > /dev/null 2>&1 || true` | |
# Start a new sync process in background | |
`vagrant gatling-rsync-auto >> rsync.log &` | |
end | |
end | |
[:halt, :suspend, :destroy].each do |trigger| | |
config.trigger.before trigger do | |
# Kill rsync-auto process | |
success "Stopping background rsync-auto process..." | |
`kill $(pgrep -f rsync-auto) > /dev/null 2>&1 || true` | |
`rm -f rsync.log` | |
end | |
end | |
end | |
# vboxsf: reliable, cross-platform and terribly slow performance | |
elsif synced_folders['type'] == "vboxsf" | |
@ui.warn "WARNING: Using the SLOWEST folder sync option (vboxsf)" | |
config.vm.synced_folder vagrant_root, vagrant_mount_point | |
# Warn if neither synced_folder not individual_mounts is enabled | |
elsif synced_folders['individual_mounts'].nil? | |
@ui.error "ERROR: Synced folders not enabled or misconfigured. The VM will not have access to files on the host." | |
end | |
# Individual mounts | |
unless synced_folders['individual_mounts'].nil? | |
@ui.success "Using individual_mounts synced folder option" | |
for synced_folder in synced_folders['individual_mounts'] do | |
if synced_folder['type'] == 'vboxsf' | |
config.vm.synced_folder synced_folder['location'], synced_folder['mount'], | |
mount_options: [synced_folder['options']] | |
elsif synced_folder['type'] == 'nfs' | |
config.vm.synced_folder synced_folder['location'], synced_folder['mount'], | |
type: "nfs", | |
mount_options: [synced_folder['options']] | |
end | |
end | |
end | |
# Make host home directory available to containers in /.home | |
if File.directory?(File.expand_path("~")) | |
config.vm.synced_folder "~", "/.home" | |
end | |
# Make host SSH keys available to containers in /.ssh (legacy, TO BE REMOVED soon) | |
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 = $vconfig['v.gui'] # Set to true for debugging. Will unhide VM's primary console screen. | |
v.name = vagrant_folder_name + "_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. | |
# Disable VirtualBox DNS proxy as it may cause issues. | |
# See https://github.com/docker/machine/pull/1069 | |
v.customize ['modifyvm', :id, '--natdnshostresolver1', 'off'] | |
v.customize ['modifyvm', :id, '--natdnsproxy1', 'off'] | |
end | |
## Provisioning scripts ## | |
# Pass vagrant_root variable to the VM and cd into the directory upon login. | |
config.vm.provision "shell", run: "always" do |s| | |
s.inline = <<-SCRIPT | |
echo "export VAGRANT_ROOT=$1" >> /home/docker/.profile | |
echo "cd $1" >> /home/docker/.ashrc | |
SCRIPT | |
s.args = "#{vagrant_mount_point}" | |
end | |
# Install dsh tool (Drude Shell) into VM's permanent storage. | |
# https://github.com/blinkreaction/drude | |
config.vm.provision "shell" do |s| | |
s.inline = <<-SCRIPT | |
# echo "Installing dsh (Drude Shell)..." | |
sudo curl -sSL https://raw.githubusercontent.com/blinkreaction/drude/master/bin/dsh -o /var/lib/boot2docker/bin/dsh | |
sudo chmod +x /var/lib/boot2docker/bin/dsh | |
sudo ln -sf /var/lib/boot2docker/bin/dsh /usr/local/bin/dsh | |
SCRIPT | |
end | |
# Let users provide credentials to log in to Docker Hub. | |
if $vconfig['docker_registry_auth'] | |
config.vm.provision "trigger", :option => "value" do |trigger| | |
trigger.fire do | |
info 'Authenticating with the Docker registry...' | |
system "docker -H localhost:2375 login" | |
end | |
end | |
config.vm.provision "file", source: "~/.docker/config.json", destination: ".docker/config.json" | |
end | |
# System-wide dnsmasq service for DNS discovery and name resolution | |
# Image: blinkreaction/dns-discovery v1.0.0 | |
config.vm.provision "shell", run: "always", privileged: false do |s| | |
s.inline = <<-SCRIPT | |
echo "Starting system-wide DNS service... " | |
docker rm -f dns > /dev/null 2>&1 || true | |
docker run -d --name dns --label "group=system" \ | |
-p $1:53:53/udp -p 172.17.42.1:53:53/udp --cap-add=NET_ADMIN --dns 8.8.8.8 \ | |
-v /var/run/docker.sock:/var/run/docker.sock \ | |
blinkreaction/dns-discovery@sha256:f1322ab6d5496c8587e59e47b0a8b1479a444098b40ddd598e85e9ab4ce146d8 > /dev/null | |
SCRIPT | |
s.args = "#{box_ip}" | |
end | |
# System-wide vhost-proxy service. | |
# Containers must define a "VIRTUAL_HOST" environment variable to be recognized and routed by the vhost-proxy. | |
# Image: blinkreaction/nginx-proxy v1.1.0 | |
if $vconfig['vhost_proxy'] | |
config.vm.provision "shell", run: "always", privileged: false do |s| | |
s.inline = <<-SCRIPT | |
echo "Starting system-wide HTTP/HTTPS reverse proxy on $1... " | |
docker rm -f vhost-proxy > /dev/null 2>&1 || true | |
docker run -d --name vhost-proxy --label "group=system" -p $1:80:80 -p $1:443:443 \ | |
-v /var/run/docker.sock:/tmp/docker.sock \ | |
blinkreaction/nginx-proxy@sha256:1707c0fd2fa4f0e98a656f748a4edb8a04578e9dc63115acc23a05225f151e04 > /dev/null | |
SCRIPT | |
s.args = "#{box_ip}" | |
end | |
end | |
# Automatically start containers if docker-compose.yml is present in the current directory. | |
# See "autostart" property in vagrant.yml. | |
if File.file?('./docker-compose.yml') && $vconfig['compose_autostart'] | |
config.vm.provision "shell", run: "always", privileged: false do |s| | |
s.inline = <<-SCRIPT | |
echo "Found docker-compose.yml in the root folder. Starting containers..." | |
cd $1 | |
docker-compose up -d | |
SCRIPT | |
s.args = "#{vagrant_mount_point}" | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment