

In this article I will try to introduce you to the wonderful utilities of Vagrant and Chef using the example of the
automatic configuration of the development environment for a PHP developer (in fact, PHP is just an example here, everything described below can be used for any technology stack).
What do we do?
')
We will configure a virtual machine (VM) with Ubuntu 12.04 to work on a project in PHP, namely:
- Apache
- MySql
- PHP 5.4
- xDebug
- Memcached
- Composer
- Configure Virtual Host right away to a specific folder accessible from a virtual machine or from a real one. All this is parameterized for ease of creation and use.
- and other..
Quite a boring thing, especially if you do it with some frequency, so we will force the computer to do it yourself.
How can this help you?
- You do not want to "litter" your system with a variety of utilities, programs
- You want to test your code in conditions close to production
- You want to test your code on different versions of this or that platform (remember how Travis tests builds in different configurations, for example, symfony on different versions of PHP)
- You do not want to help a new person on a project (layout designer, programmer) to install everything from scratch
- You want every person in the team to have an identical environment for working on the project.
All this is reality. The only question is "how?"
Vagrant
Vagrant is a utility that allows you to create a virtual machine and configure it automatically as you specified. Out of the box, Vagrant works with VirtualBox, although
there is support for other solutions.
Looking ahead, all you need in order to deploy the environment on your computer is to run one command:
vagrant up
Everything will be done automatically. Let's get down to our task.
To configure Vagrant uses only one file -
Vagrantfile . That is what describes everything that needs to be done when starting a virtual machine. To initialize the Vagrant project, you must run the command
vagrant init
at the root of your project.
We have the following directory structure:
recipes www Vagrantfile
One of the main concepts in Vagrant is box. Box is an archive that contains an image of a virtual machine and a file with settings for Vagrant itself.
We'll use the box from the Vagrant website (each box includes at least the installed Chef, Puppet - this will be very useful for us a bit later).
The final Vagrantfile file will look like this (standard comments have been removed, see their documentation):
Used by Ruby to describe the configuration file.
It makes no sense to describe all the details and trivialities of Vagrant, they can (and even should) be read in the documentation. It, by the way, is written well.
In the file we specify the name for the box. If it has not yet been downloaded, Vagrant will do it automatically and save it to your hard drive. For this, there is a URL where the box can be found. It is possible to specify the path in the file system.
In the
network property, we indicate that the VM will be available on IP 11.11.11.11. This is done in order to be able to create and use several projects, defining names for them and storing the file of our real computer into the hosts.
Ports can also be used here: in this example
... config.vm.forward_port 80, 8080 ...
we configure the VM so that on port 8080 from the host machine we get to port 80 of the guest machine. (in the Vagrant documentation, the host machine is our computer, the guest machine is a virtual machine). Read more
here .
The
share_folder property allows you to configure shared folders for the host machine and the guest machine. It is very convenient. You open your IDE and work with files located on your computer, not on the VM (although you can set up the editor to work with remote files), and they are instantly synchronized. By default, the folder with your project will be available on the VM along the
/vagrant
. In our case, we make available the
www
folder on the host machine along the path
/var/www
on the guest machine.
Next come the Chef settings, which will be described below. With the help of Chef, all the necessary software will be installed.
Here we
have a choice , you can use:
- Chef
- Puppet
- bash scripts
Chef
Chef is a utility for managing configurations, project deployment, and more. In conjunction with Vagrant, we will use Chef to install all the software, as well as to create VirtualHost and the folders of the new project. Links to interesting articles on using Chef in clusters are provided at the end of the article.
Here a question may arise - how can you install so much of everything automatically? Here comes a large community of Chef and official
cookbooks from its creators.
A cookbook is a collection of recipes, templates, attributes, and other settings files for Chef. For example, there is the
Apache2 cookbook, with which Chef will put apache on your OS.
It is not clear what are recipes, templates, attributes? Do not worry, there is
an excellent article that will shed light and help you deal with Chef very quickly. Below in the article we will create our own cookbook and everything will become even more transparent.
To install all the necessary software, we will use the following existing cookbooks:
- Apache2
- Mysql
- Php
- Vim
- Composer
- and others (some cookbooks are dependent on others, so you have to add them)
It is for Chef in our directory structure that the
recipes folder exists.
Software installation process
For convenience, you can install Chef on the host machine to use
knife to generate the basic folder structure for the new cookbook. This step is absolutely optional.
Run the following command as root:
curl -L https://www.opscode.com/chef/install.sh | bash
At the root of our project we make a config for Knife:
mkdir .chef echo "cookbook_path [ '/path-to/recipes/cookbooks' ]" > .chef/knife.rb
Create our own cookbook. It will run after the standard ones, when all the software is already installed, and will create VirtualHost with the specified domain name and with the specified path to the project, as well as create a database with the specified name. Let's call it
app .
knife cookbook create app
Our cookbook will depend on the standard
Database and, of course, on
Apache2 , so add dependencies:
/path-to/recipes/cookbooks/app/metadata.rb name 'app' maintainer 'YOUR_COMPANY_NAME' maintainer_email 'YOUR_EMAIL' license 'All rights reserved' description 'Installs/Configures app' long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) version '0.1.0' depends "apache2" depends "database"
Set the cookbook
database for example. Since I installed Chef locally, I can take advantage of the possibilities of knife. Otherwise, you can simply
download from github and copy it to the
/ path-to / recipes / cookbooks folder:
cd recipes/cookbooks/ knife cookbook site download database tar zxf database-*.tar.gz rm *.tar.gz
It also installs any other cookbook we need.
Creating VirtualHost for Apache
Create a template:
/path-to/recipes/cookbooks/app/templates/default/vhost.erb <VirtualHost *:80> ServerAdmin <%= @params[:server_email] %> ServerName <%= @params[:server_name] %> DocumentRoot <%= @params[:docroot] %> <Directory <%= @params[:docroot] %>> Options Indexes FollowSymLinks MultiViews AllowOverride ALL Order allow,deny Allow from all </Directory> ErrorLog ${APACHE_LOG_DIR}/<%= @params[:server_name] %>.log LogLevel debug </VirtualHost>
As you have noticed, variables can be used in the template (set via attributes). We will save the default values for them in a separate file:
/path-to/recipes/cookbooks/app/attributes/default.rb default["app"]["database"] = "app" default["app"]["path"] = "/var/www/vm-app" default["app"]["server_name"] = "vm-app" default["app"]["server_email"] = "vm.app@example.com"
And let us redefine all variable through Vagrantfile.
Vagrantfile ... chef.json = { "app" => { "path" => "/var/www/cool-another-app", "server_name" => "cool-another-app", "server_email" => "cool@another-app.com", "database" => "cool_another_app_db" }, "mysql" => { "server_root_password" => "%your_path0%", "server_repl_password" => "%your_path1%", "server_debian_password" => "%your_path2%" } } ...
Great, it remains to use Chef to create the desired folder, and create a specific virtual host file. All this can be done through auxiliary functions, called resources. We write these actions directly in the recipe:
/path-to/recipes/cookbooks/app/recipes/default.rb At the same time, Chef will do everything automatically. In our case: add the site to
/ etc / apache2 / sites-available and execute
a2ensite server_nameA list of all available resources can be found in the
documentation .
Creating a database
To do this, we simply add the following code to the
/path-to/recipes/cookbooks/app/recipes/default.rb file:
mysql_database node['app']['database'] do connection ({:host => 'localhost', :username => 'root', :password => node['mysql']['server_root_password']}) action :create end
The list of all cookbooks that Chef needs to perform is configured in the run_list array in the file:
/path-to/recipes/roles/web.json { "name": "web", "default_attributes": { }, "override_attributes": { }, "json_class": "Chef::Role", "description": "web server role", "chef_type": "role", "run_list": ["recipe[apt]", "recipe[chef-dotdeb]", "recipe[chef-dotdeb::php54]", "recipe[apache2]", "recipe[apache2::mod_php5]", "recipe[apache2::mod_rewrite]", "recipe[php]", "recipe[mysql]", "recipe[mysql::server]", "recipe[app]", "recipe[composer]", "recipe[sqlite]", "recipe[vim]", "recipe[cron]", "recipe[ntp]"] }
That's all! Our environment is ready to check. Perform in the project root:
vagrant up
After this command, Vagrant initializes the specified box and starts installing all necessary software.
What do we have in the end?
As a result, we have a fully configured virtual machine. SSH access. To do this, simply execute
vagrant ssh
After adding the IP address and the name of the test site to the hosts, you simply open it in the browser on the host machine, and the code runs on the VM.
The important point is to maintain the state of the VM. If this is not done, then after each launch via
vagrant up
, the software will be
reinstalled . At the same time, the whole point of our idea is lost. To solve this situation, Vagrant has the following commands:
- vagrant suspend - saves the current state and after the
vagrant up
command, work continues from the saved point - vagrant halt - turns off VM
After executing these commands, you can safely restart the OS and resume work again.
To destroy all resources associated with a VM, use the
vagrant destroy command.
Some articles advise keeping the database on the host machine so as not to risk data loss.
With the help of Vagrant, it is also possible to raise a test cluster, while the communication between virtual machines is configured via the
network config property.
Useful links for reading
For those who are interested, I suggest to get acquainted with the following resources:
Vagrant + Chef environment files that were configured in this article.Vagrant:- docs.vagrantup.com/v2 - documentation. Required to read.
- www.vagrantbox.es - list of boxes on all popular OS
- habrahabr.ru/post/140714
- net.tutsplus.com/tutorials/setting-up-a-staging-environment is a very cool article on setting up a staging environment. Required to read.
- www.phptherightway.com - php developers
Chef:- docs.opscode.com - official website
- docs.opscode.com/resource_deploy.html - deployment
- gettingstartedwithchef.com - must be read. Reveals all the basic things Chef
- habrahabr.ru/company/scalaxy/blog/87302
Thanks to everyone who read to the end. I hope the article turned out to be useful and caused you positive emotions, as is the case with those who hear, for example, about Vagrant for the first time.
I apologize in advance for inaccuracies and, possibly, technical illiteracy in one form or another.