It Works On My Machine

Virtualizing Development

by Eli Golding / eligolding@gmail.com / @eli_golding

Why Virtualize?

Traditional setup

Individual local development machines

new dev joins the team they must...

install web server (apache/nginx)...

install PHP...

install MySQL...

install Redis, Memcache, NPM, RVM...

we're not done...

configure all the things...

get the code...

attempt to serve the application...

configure some more things to get it to work...

Dev #1

  • Apache 2.2.15
  • PHP 5.5.4
  • MySQL 5.4.5

Dev #2

  • Apache 2.2.3
  • PHP 5.5.1
  • MySQL 5.4.3

Dev #3

  • Apache 2.2.24
  • PHP 5.4.3
  • MySQL 5.2.5

Dev #4

  • Apache 2.1.8
  • PHP 5.3.24
  • MySQL 5.1.6

IT Automation Tools

Problems with using just a provisioner

Still bound to hardware

Can only have one setup

Inflexible infrastructure

Potential to cause problems with main OS

Port conflicts

Different type of machine than production

Virtualization

“Virtualization, in computing, refers to the act of creating a virtual (rather than actual) version of something, including but not limited to a virtual computer hardware platform, operating system (OS), storage device, or computer network resources.”

Virtualization Providers

Virtualization the good parts

  • Multiple VMs on one machine
  • Flexibility
  • Doesn't mess up your host machine
  • Dev == Production

Virtualization the not so good parts

  • Setup is very time consuming
  • Must distribute it
  • Maintain and Update
  • Redistribute

Vagrant is a command line tool that fully controls the creation and provisioning of virtual machines.

Everything is configured in a single file (VagrantFile) that part of the project.

Can be viewed as a wrapper around the VM provider and the provisioner.

The VagrantFile is checked into version control, allowing for great portability.

So now we have

  • Easy to share
  • Same exact version across all systems
  • Fast ramp up
  • "WORKS ON OUR MACHINE"

VagrantFile


  Vagrant.configure(2) do |config|

	config.vm.box = "ubuntu/trusty64"

	config.vm.network "forwarded_port", guest: 80, host: 8080

	config.vm.network "private_network", ip: "192.168.33.10"

	config.vm.synced_folder ".", "/var/www"

	config.vm.provision "shell", inline: <<-SHELL
	  sudo apt-get install -y apache2
	SHELL

  end
				

Box


  config.vm.box = "ubuntu/trusty64"
				

Configures the base box of the machine. Value should be the name of an installed box or a shorthand name of a box in HashiCorp's Atlas.

Network


  config.vm.network "forwarded_port", guest: 80, host: 8080

  config.vm.network "private_network", ip: "192.168.33.10"
				

Configures networks on the machine.

Synced Folder


  config.vm.synced_folder ".", "/var/www"
				

Synced folders enable Vagrant to sync a folder on the host machine to the guest machine, allowing you to continue working on your project's files on your host machine.

Provision


  config.vm.provision "shell", inline: <<-SHELL
    sudo apt-get install -y apache2
  SHELL
				

Set the Provisioners that will automatically install software, alter configurations, and more on the machine as part of the vagrant up process.

Vagrant Commands

  • vagrant up: start a new instance of the VM
  • vagrant suspend: save state of the running VM
  • vagrant resume: restart suspended VM
  • vagrant halt: powers off VM
  • vagrant reload: reboot VM
  • vagrant destroy: Completely deletes the machine

Infrastructure as Code

Resource

Represents a piece of your infrastructure and it's desired state.

Common Resources

Running a Command


  execute "composer-install" do
    cwd '/var/www/app'
    command "composer install"
  end
					

Changing directory permissions


  directory "/vagrant/app/cache" do
    owner "vagrant"
    group "vagrant"
    mode 0777
    action :create
  end
					

Creating a symlink


  link "/etc/nginx/sites-enabled/my-cool-site" do
    to "/etc/nginx/sites-available/my-cool-site"
  end
					

Running apt-get update


  execute "apt-get update" do
    command "apt-get update"
  end					

Installing a package


  apt_package "curl" do
    action :install
  end
					

Installing multiple packages


  php_packages = ['php5-cli','php5-curl','php5-mysql']

  php_packages.each do |p|
    apt_package p do
      action :install
    end
  end
					

Applying a template


  template "/etc/nginx/sites-available/my-awesome-site" do
    source "vhost.erb"
    variables({
      :doc_root    => '/var/www',
      :server_name => 'vagrant.rox'
    })
    action :create
    notifies :restart, resources(:service => "nginx")
  end
					

  server {
      listen   80;

      root <%= @doc_root %>;
      index index.html index.php;

      server_name <%= @server_name %>;

      location / {
          try_files $uri $uri/ /index.php;
      }

      error_page 404 /404.html;

      error_page 500 502 503 504 /50x.html;
      location = /50x.html {
          root /usr/share/nginx/www;
      }

      location ~ \.php$ {
          fastcgi_split_path_info ^(.+\.php)(/.+)$;
          fastcgi_pass unix:/var/run/php5-fpm.sock;
          fastcgi_index index.php;
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
          include fastcgi_params;
      }
  }
					

Recipe

Configuration file that describes resources and their desired state.

Cookbook

Recipes are stored in cookbooks.

Cookbook contain recipes, template, files, custom resources, etc.

"If you want to increase innovation, you have to lower the cost of failure."
  • Joi Ito
  • Director, MIT Media Lab

Questions?