Webdevelopment workflow met Vagrant en Chef
Ontwikkelen binnen een VM
Ik ga hier niet uitgebreid in op de voordelen van het ontwikkelen binnen een Virtual Machine, want daar is genoeg over te vinden op het web. Er zitten nadelen aan vast, maar voor mij wegen die niet op tegen de enorme voordelen. Het biedt mij een enorme flexibiliteit en 'schoonheid' van mijn systeem, alhoewel ik me voor kan stellen dat als je niet, zoals ik, louter met PHP en Python werkt voor web-applicaties en je meer aan de .NET kant doet het verhaal wellicht anders is.Mijn insteek is, net als in veel programmeertalen het geval is, seperation of concerns. Mijn computer is geen webserver en geen database server. Het is wél een ontwikkelbak waar op getypt kan worden. Mijn server is geen ontwikkelbak waar tools opstaan zoals PHPStorm en SublimeText, maar wél Apache2 en PHP5. Verder niks.
Idealiter wil ik dus een VM hebben waar alles op draait en ik zonder al te veel gedoe mijn code die ik aan het tikken ben live kan zetten op de server en het daar kan zien.
Vagrant
Laat dit nu net zijn waar Vagrant goed in is! En dan knippen ze de laatste stap eruit, want het live zetten hoeft niet eens. Ik ontwikkel direct op de VM, mét mijn eigen tools op mijn eigen bak.Ik ga hier geen tutorial neerplempen van Vagrant, want dat kunnen die mannen en vrouwen prima zelf. Ik zou maar eens kijken op: www.vagrantup.com: Getting Started With Vagrant. Die tutorial kost je 10 minuten en dan snap je precies wat ik bedoel.
Web-app development met Vagrant
Op naar de hoofdmoot van mijn verhaal. Ik ga een basis Apache2 server met PHP hier maken met de volgende eisen.- Debian-like server 32 bit, hetzelfde als op mijn VPS draait
- Apache2
- PHP5.3.8 of hoger
- php_apc (voor het cachen van php-code en data)
- XDebug (voor het debuggen)
Ik ontwikkel alles op OSX, dus alle commandos zijn terminal commands binnen de terminal van OSX. Alle commandos zijn vanuit een directory ergens in mijn home-dir (~/Vagrant/php-dev), maar dat mag je natuurlijk helemaal zelf kiezen.
Vagrant base-box installeren
Het project is gestart en nu ga ik een vagrant instantie toevoegen aan dit project. Het gaat een VM zijn gebaseerd op Ubuntu Precise 32 welke al in base-box vorm bestaat gemaakt door de lui van Vagrant zelf. Andere base-boxes kan je hier en hier vinden. Informatie over het maken van een eigen base box staat hier.Tijd om de base-box te downloaden, een VM te maken in de map vagrant en hem te starten.
$ mkdir vagrant $ cd vagrant $ vagrant box add precise32 http://files.vagrantup.com/precise32.box [vagrant] Downloading with Vagrant::Downloaders::HTTP... [vagrant] Downloading box: http://files.vagrantup.com/precise32.box [vagrant] Extracting box... [vagrant] Verifying box... [vagrant] Cleaning up downloaded box... $ vagrant init precise32 A `Vagrantfile` has been placed in this directory. You are now ready to `vagrant up` your first virtual environment! Please read the comments in the Vagrantfile as well as documentation on `vagrantup.com` for more information on using Vagrant.
Zoals je ziet heb ik de base box gedownload van een webserver en hem lokaal precise32 genoemd. Daarna heb ik met het init command een nieuwe Vagrant box aangemaakt gebaseerd op de precise32 base box.
De VM staat klaar! Tijd om hem te runnen.
$ vagrant up [default] Matching MAC address for NAT networking... [default] Clearing any previously set forwarded ports... [default] Forwarding ports... [default] -- 22 => 2222 (adapter 1) [default] Creating shared folders metadata... [default] Clearing any previously set network interfaces... [default] Booting VM... [default] Waiting for VM to boot. This can take a few minutes. [default] VM booted and ready for use! [default] Mounting shared folders... [default] -- v-root: /vagrant
Zoals je merkt is ie eerst bezig met het kopieren van de precise32 base box en daarna start ie! De SSH port 22 op het VM systeem wordt doorgelust naar onze eigen 2222 port number, dus we kunnen gewoon SSH'en naar 127.0.0.1:2222 en dan zitten we in het Vagrant systeem.
Gelukkig heeft Vagrant ook gewoon het ssh commando zodat we even kunnen rondneuzen op het systeem.
$ vagrant ssh Welcome to Ubuntu 12.04 LTS (GNU/Linux 3.2.0-23-generic-pae i686) vagrant@precise32:~$ ls / bin dev home lib media opt root sbin srv tmp vagrant vmlinuz boot etc initrd.img lost+found mnt proc run selinux sys usr var vagrant@precise32:~$ ls /vagrant Vagrantfile vagrant@precise32:~$ logout
Zoals je ziet is er een root folder /vagrant bijgekomen welke letterlijk naar onze Vagrant folder op onze host verwijst. Zoals je ziet staat daar de Vagrantfile waar het hele systeem in gedefinieerd wordt. Door zo folders te mounten naar ons host systeem kunnen we makkelijk een web-applicatie op ons host systeem houden en hem gewoon draaien binnen het VM als web-app.
Provisioning Vagrant met Chef Solo
Chef Solo is een onderdeel van Opscode Chef waar je hele installaties mee kan automatiseren, wat ook wel provisioning genoemd wordt. Meer over provisioning van Vagrant kan je hier lezen.Laten we de Vagrantfile aanpassen naar een basis waarmee we kunnen gaan provisionen met Chef:
1
2
3
4
5
6
7
8
9
10
11
12
| Vagrant::Config.run do |config| config.vm.box = "precise32" # ik zorg voor 2 virtuele netwerkkaarten, zodat ik onderling VM's ook makkelijk met elkaar kan laten communiceren (denk aan PHP -> MySQL) config.vm.network :hostonly, "33.33.33.10" config.vm.network :bridged config.vm.forward_port 80, 8080 # ik forward port 80 op de guest naar 8080 op de host config.vm.provision :chef_solo do |chef| chef.cookbooks_path = "cookbooks" end end |
Op het moment is er nog geen enkel Chef recipe ingeladen maar denkt ie z'n cookbooks, met daarin recipes, in de cookbook folder relatief t.o.v. de Vagrantfile te vinden, dus laten we die maken.
$ mkdir cookbooks
Nu is het tijd om de cookbooks op te halen die Opscode al gemaakt heeft of elders online beschikbaar zijn. In ons geval gaat het om apt, apache2, php cookbooks. De apt-cookbook gebruik ik omdat dan de aptitude repositories elke keer geupdate worden en voor het toevoegen van eventuele andere repositories. Voor meer cookbooks raadt ik je aan te kijken op de Opscode Github. Daar kan je van alle cookbooks alle broodnodige informatie vinden.
Tijd om de cookbooks binnen te halen met Git:
$ git clone git://github.com/opscode-cookbooks/apt.git cookbooks/apt $ git clone git://github.com/opscode-cookbooks/apache2.git cookbooks/apache2 $ git clone git://github.com/opscode-cookbooks/php.git cookbooks/php
en om ze te activeren in de Vagrantfile:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| Vagrant::Config.run do |config| config.vm.box = "precise32" config.vm.network :hostonly, "33.33.33.10" config.vm.network :bridged config.vm.forward_port 80, 8080 config.vm.provision :chef_solo do |chef| chef.cookbooks_path = "cookbooks" chef.add_recipe("apt") chef.add_recipe("apache2") chef.add_recipe("apache2::mod_php5") chef.add_recipe("php") end end |
Nu moeten we Vagrant box opnieuw opstarten de configuratie te harladen en om Chef z'n gang te laten gaan:
$ vagrant reload [default] Attempting graceful shutdown of VM... [default] Clearing any previously set forwarded ports... [default] Forwarding ports... [default] -- 22 => 2222 (adapter 1) --- knip --- $ vagrant ssh vagrant@precise32:~$ apachectl -v Server version: Apache/2.2.22 (Ubuntu) Server built: Nov 8 2012 21:37:45 vagrant@precise32:~$ php -v PHP 5.3.10-1ubuntu3.4 with Suhosin-Patch (cli) (built: Sep 12 2012 19:00:43) Copyright (c) 1997-2012 The PHP Group Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies vagrant@precise32:~$ logout
Voila, Apache2 en PHP5.3.10 staan erop! Momenteel draait er nog geen enkele website. Tijd om een website toe te voegen.
Web applicatie toevoegen
Als je bekend bent met Apache2 dan weet je dat je een conf bestand kan maken met de Virtualhost gegevens en die vervolgens in de sites-available directory kan activeren. Gelukkig kan dit ook allemaal met Chef. We maken een eigen recipe welke onze Virtualhost configureert en bijkans ook APC en XDebug installeert.Begin met het maken een eigen cookbook met bijbehorende mappenstructuur en Ruby files (voor meer informatie over eigen recipes moet je de Chef documentatie lezen):
$ mkdir cookbooks/custom_app $ mkdir cookbooks/custom_app/attributes $ mkdir cookbooks/custom_app/recipes $ mkdir cookbooks/custom_app/templates $ mkdir cookbooks/custom_app/templates/default $ touch cookbooks/custom_app/recipes/default.rb $ touch cookbooks/custom_app/attributes/default.rb $ touch cookbooks/custom_app/templates/default/custom_app.conf.erb
De laatste is een Ruby template waarmee we de VirtualHost conf maken.
En de inhoudt van de bestanden:
cookbooks/custom_app/attributes/default.rb
1
2
| default['custom_app']['server_name'] = 'web-app.dev' default['custom_app']['docroot'] = '/web-app' |
cookbooks/custom_app/templates/default/custom_app.conf.erb
1
2
3
4
5
6
7
8
9
10
11
| <VirtualHost *:80> ServerName <%= @params[:server_name] %> DocumentRoot <%= @params[:docroot] %> <Directory <%= @params[:docroot] %>> Options FollowSymLinks AllowOverride All Order allow,deny Allow from all </Directory> </VirtualHost> |
Als laatste hebben we de daadwerkelijke recipe nodig:
cookbooks/custom_app/recipes/default.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| app_name = 'custom_app' app_config = node[app_name] # install APC package "php-apc" do action :install end # install XDebug package "php5-xdebug" do action :install end # set up the Apache virtual host web_app app_name do server_name app_config['server_name'] docroot app_config['docroot'] template "custom_app.conf.erb" end |
Zoals je ziet halen we in het begin een app_config op (welke naar de attributes verwijst of in onze Vagrantfile te definieren is), dan worden APC en XDebug middels aptitude geinstalleerd en daarna renderen we vhost.conf met die attributes.
Zoals je ziet in attributes/default.rb is de doc-root van onze website op /web-app in ons guest VM. Laten we die even toevoegen en mappen naar een map op onze host. Ik maak op onze host een map aan genaamd web-app welke 1 niveau hoger ligt dan de vagrant map. Dan houd ik alles netjes gescheiden:
$ mkdir ../web-app $ ls ../ vagrant web-app
En om een mapping toe te voegen passen we onze Vagrantfile als volgt aan:
1
2
3
4
5
| --- knip --- config.vm.network :bridged config.vm.forward_port 80, 8080 config.vm.share_folder "web-app", "/web-app", "../web-app" # voeg deze regel toe. --- knip --- |
Hier voegen we een nieuwe mapping, genaamd web-app toe welke /web-app op onze guest mount op ../web-app op onze host.
Nu moeten we alleen onze web-app nog via Chef toevoegen, door hem in onze Chef lijst in de Vagrantfile te zetten:
1
2
3
4
5
6
7
8
9
| --- knip --- config.vm.provision :chef_solo do |chef| chef.cookbooks_path = "cookbooks" chef.add_recipe("apt") chef.add_recipe("apache2") chef.add_recipe("apache2::mod_php5") chef.add_recipe("php") chef.add_recipe("custom_app") # voeg hier onze eigen recipe toe end |
En tijd om een documentje in de web-app folder te zetten en Vagrant te starten:
$ echo "<?php phpinfo(); ?>" > ../web-app/index.php $ vagrant reload
Als het goed is draait onze web-applicatie nu op een Apache2 server binnen een Ubuntu distributie op onze VM maar is ie te benaderen vanuit localhost:8080. Even checken of het zo is:

Jawel! Het werkt allemaal, en zoals je kan zien zijn XDebug en APC ook aanwezig.
Gebruik van de box voor verder gebruik
Het mooie is dat deze VM nu helemaal gedefinieerd wordt door de Vragrantfile en de bijbehorende cookbooks. Het enige wat ik hoef te doen om deze VM te hergebruiken is de map vagrant kopieren en dan kan ik hem voor andere web-applicaties gebruiken. Voordat je zo'n kopieeractie doet is het wel handig alle gegenereerde data van vagrant up, weg te halen zodat je schoon kan beginnen.$ vagrant destroy
Zelf heb ik een vergelijkbare box als Git repository ergens staan en die clone ik dan in mijn projecten. In mijn .gitignore van het project staat dan simpelweg /vagrant zodat de VM netjes gescheiden staat van mijn source.
Het aanpassen van attributes is ook geen enkel probleem en kan vanuit onze Vagrantfile. Hiervoor verwijs ik je naar de Chef documentatie. In ons geval kan een je de custom_app attributen als volgt aanpassen in de Vagrantfile:
1
2
3
4
5
6
| chef.json = { "custom_app" => { "server_name" => 'symfony2-app.dev', "docroot" => '/web-app/web' } } |
Zoals je ziet kan dat voor krachtige flexibiliteit zorgen.
Afsluiting
Dit is een hele korte introductie van Chef en Vagrant, maar hopelijk laat het z'n kracht zien. Ik raadt je zeker aan de volgende sites te bezoeken voor meer informatie:http://www.vagrantup.com
http://wiki.opscode.com/display/chef/Home
http://www.jasongrimes.or...f-vagrant-and-ec2-3-of-3/
https://github.com/opscode-cookbooks
https://github.com/simshaun/symfony-vagrant
Ik vind Vagrant best een innovatieve manier om mijn PHP-applicaties te ontwikkelen, zonder dat het mijn host bevuilt en hopelijk heb ik dat duidelijk kunnen maken
Mochten er op- of aanmerkingen zijn, schroom dan niet, want aangezien dit mijn eerste post is zullen er wel wat dingen onduidelijk danwel fout ingezet zijn.
04-'15 Mijn eerste nummer sinds lange tijd
Reacties
code:
1
2
3
4
| The VM failed to remain in the "running" state while attempting to boot. This is normally caused by a misconfiguration or host system incompatibilities. Please open the VirtualBox GUI and attempt to boot the virtual machine manually to get a more informative error message. |
Ik ga nu nog even de juiste virtualbox installeren, (heb een te hoge versie) hopelijk is het dan opgelost.
EDIT: opgelost, ik moest het vboxnetflt nog inladen via modprobe.
[Reactie gewijzigd op zaterdag 12 januari 2013 13:23]
[Reactie gewijzigd op zaterdag 12 januari 2013 13:44]
Het PHPMyAdmin cookbook.
Het MySQL cookbook.
Voor MySQL moet je ook nog openssl installeren. Het openssl cookbook.
Ergens in de readme's staat iets van een JSON array. Deze moet je gewoon in het Vagrantfile zetten, net boven de cookbooks:
Ruby:
1
2
3
4
5
6
7
| chef.json = { "mysql" => { "server_root_password" => "vagrant", "server_repl_password" => "vagrant", "server_debian_password" => "vagrant" } } |
Ik bedankt je heel hard voor deze tutorial. Ik heb er veel van geleerd en deze manier van werken staat me wel aan. Ben je er al lang mee bezig? Zoja wat zijn je bevindingen? Werkt dit op langere termijn ook nog goed?
Ik zie hier veel mogelijkheden voor, maar helemaal als je Chef op een server deployed en zo je server configuratie managed.
Voor mij is het gewoon het belangrijkst om zo min mogelijk inmenging van web-apps en andere dingen op mijn host systeem te hebben.
Bedankt voor je complimenten
Reageren is niet meer mogelijk