Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Full-Stack CakePHP Deployment

Full-Stack CakePHP Deployment

Deploying CakePHP applications using Capistrano and Chef. Covering both server - MySQL/nginx/php - and application deployment, as well as existing tools and usage examples.


Jose Diaz-Gonzalez

September 03, 2011


  1. FULL-STACK CAKEPHP DEPLOYMENT Pay attention to this corner



  4. ~WHOAMI • Jose Diaz-Gonzalez • Resident IRC Troll (savant) •

    Rants at http://josediazgonzalez.com • Harasses as @savant • Codes as josegonzalez on github • EMPLOYED at @seatgeek I’m also hot like sriracha sauce ➘ me ➘ not me
  5. WHO IS THIS TALK FOR? • Devs/Sysadmins not afraid of

    Ruby • Developers who don’t have time to waste with sysops • Sysadmins who are looking to automate more of their workflow Also anyone who couldn’t get into Mark’s talk
  6. WHY AM I SPEAKING ABOUT THIS? • I’m no Sysadmin;

    Sysadmining on half of the projects I’m on • Devs do servers wrong; Perhaps I do too • PHPNut Parole Policy (PPP) My Crime: The Patriot Ale House
  7. WHAT THE HELL IS THIS • Being lazy • Deploying

    a SERVAR • CHARGING LAYSHURS • What about the app? ¡¡¡SHOOP DA WOOP!!!
  8. IN THE BEGINNING There was PHPNut, and all was good

  9. • Geared towards automated deployments of workstations, not servers •

    Convergence implies we may never be within compliance • Community maintained packages? #  Every  policy  must  have  a  bundlesequence body  common  control { bundlesequence    =>  {  "test"  }; inputs  =>  {  "cfengine_stdlib.cf"  }; } bundle  agent  test { files: #  This  is  a  throw-­‐away  comment,  below  is  a  full-­‐bodied  promise  "/tmp/testfile"                                            #  promiser      comment  =>  "This  is  for  keeps...",  #  Live  comment        create  =>  "true",                                  #  Constraint  1          perms  =>  m("612");                              #  Constraint  2,  rw-­‐-­‐-­‐x-­‐ w-­‐ } I love it when an automation tool makes a promise

  11. MODULES AND CLASSES http://forge.puppetlabs.com/ #  ntp-­‐class1.pp class  ntp  {  

     case  $operatingsystem  {        centos,  redhat:  {              $service_name  =  'ntpd'            $conf_file        =  'ntp.conf.el'        }        debian,  ubuntu:  {              $service_name  =  'ntp'            $conf_file        =  'ntp.conf.debian'        }    }        package  {  'ntp':        ensure  =>  installed,    }        service  {  'ntp':        name            =>  $service_name,        ensure        =>  running,        enable        =>  true,        subscribe  =>  File['ntp.conf'],    }        file  {  'ntp.conf':        path        =>  '/etc/ntp.conf',        ensure    =>  file,        require  =>  Package['ntp'],        source    =>  "/root/learning-­‐manifests/${conf_file}",    } } Free beer to the first person to raise their hand
  12. WE CAN DO BETTER If we couldn’t, this would be

    the end of my talk
  13. now we’re cooking!

  14. WHY CHEF? • Uses a Ruby DSL; Doesn’t re-invent the

    wheel • Officially-sanctioned Cookbooks • Community-supported Cookbooks • All the cool rails developers are using it • Awesome logo • Screams when things are broken • Extensive Documentation And the obvious Chef/CakePHP pun
  15. HOW IS DEPLOYMENT FORMED? • Each server can have one

    or more cookbooks • Cookbooks are like plugins (nginx, apache, memcache) that can depend upon/require one another • Cookbooks have recipes, libraries, templates, definitions, files • Recipes are sets of instructions I vote we rename “plugins” to “recipes”
  16. git  "#{node[:server][:production][:dir]}/#{hostname}/#{base}/public"  do    repository  info[:repository]    user  "deploy"  

     group  "deploy" end ➘ ➘ resource name of resource options WHAT’S IN A RESOURCE CALL? http://wiki.opscode.com/display/chef/Resources ➘ special node var ➘
  17. ROLL YOUR OWN RESOURCES? Yo dawg, I hurd u liek

    yo yos so I gave yo dawg a yo yo so yo dawg can yo yo while yo dawg yo yos yo dawg yo
  18. #  Definition define  :nginx_up,  :enable  =>  true  do    template

     params[:name]  do        source  "html.erb"        owner  "deploy"        group  "deploy"        mode  0644        variables(params[:variables])    end    nginx_site  params[:hostname]  do        action  :enable    end end #  Usage nginx_up  "#{node[:nginx][:dir]}/sites-­‐available/#{hostname}.#{base}"  do    hostname  "#{info[:hostname]}.#{info[:base]}"    variables(info[:variables]) end “Fake” resources, for more info see http://wiki.opscode.com/display/chef/Providers Resources on the Cheap ➘ Just chain resources ➘ Fire at will
  19. node[:static_applications].each  do  |hostname,  sites|    sites.each  do  |base,  info|  

         directory  "#{node[:server][:production][:dir]}/#{hostname}/#{base}"  do                owner  "deploy"                group  "deploy"                mode  "0755"                recursive  true        end        git  "#{node[:server][:production][:dir]}/#{hostname}/#{base}/public"  do            repository  info[:repository]            user  "deploy"            group  "deploy"        end        nginx_up  "#{node[:nginx][:dir]}/sites-­‐available/#{hostname}.#{base}"  do            hostname  "#{hostname}.#{base}"            variables(info[:variables])        end    end end ALL TOGETHER NOW Simplified version of something in production use
  20. server  {    listen            

     80;    server_name    <%=  @subdomain  %><%=  @hostname  %>  www.<%=  @subdomain  %><%=  @hostname  %>;    root                  <%=  @root  %>;    index                index.html  index.htm;    error_page      500  501  502  503  504    /error_500.html;    charset            utf-­‐8;    access_log      <%=  @node[:nginx][:log_dir]  %>/<%=  @subdomain  %><%=  @hostname  %>-­‐access.log;    error_log        <%=  @node[:nginx][:log_dir]  %>/<%=  @subdomain  %><%=  @hostname  %>-­‐error.log;    #  remove  www  from  the  url    if  ($host  ~*  www\.(.*))  {        set  $host_without_www  $1;        rewrite  ^(.*)$  http://$host_without_www$1  permanent;    } } ^ FROM THIS ^ here it comes...
  21. server  {    listen            

     80;    server_name    areyousmokingcrack.com  www.areyousmokingcrack.com;    root                  /apps/production/areyousmokingcrack.com/default;    index                index.html  index.htm;    error_page      500  501  502  503  504    /error_500.html;    charset            utf-­‐8;    access_log      /var/log/nginx/areyousmokingcrack.com-­‐access.log;    error_log        /var/log/nginx/areyousmokingcrack.com-­‐error.log;    #  remove  www  from  the  url    if  ($host  ~*  www\.(.*))  {        set  $host_without_www  $1;        rewrite  ^(.*)$  http://$host_without_www$1  permanent;    } } ^ TO THIS ^ this site actually exists
  22. DEMO stop using the internet please

  23. SERVER DNA • An instance is defined as a JSON

    DNA file • dna.json reference both recipes and configurations • Modifying DNA should reconfigure server • DNA can be versioned with the app You too can be a Geneticist
  24. BACK TO CAKE? • Define one set of cookbooks, use

    everywhere • Share, collaborate, grow optimized server cookbooks • Define servers in terms of DNA files: lb.json, db.json, web.json, etc. • Automate server deployment: • server new lb.json • CakePHP http://bit.ly/cakechef Contributions welcome, documentation being fleshed out
  25. DEMO you can start using the internet now

  26. WHAT ABOUT THE APP? what about it? INCEPTION

  27. BASH • Usable everywhere • Easy to read/write • Everything

    is custom; Don’t be your own giant Have fun handling multiple server types
  28. FREDISTRANO NO Never use something just because it’s written in

  29. PHING NO Yo dawg, I hurd u liek XML

  30. ANT I’ll cut you So I put some RDFA in

    your XML so you can SPARQL while you parse
  31. 23 DEPLOYMENT TOOLS LATER It’s like deployment tools are project

    management software, sheesh
  32. CAPISTRANO • MOAR Ruby • Similar in concept to Chef

    - has deployment strategies • Separates related tasks into namespaces (deploy, migration, etc.) • Easy to extend and manipulate • Docs are a bit hazy at the moment • Geared towards SCM users http://capistranorb.com
  33. INSTALL • Install Ruby/RubyGems • gem install capistrano • cd

    path/to/local/app/repository • capify . the other 8 steps of the process involve alcohol
  34. CAPIFY? • “capify .” creates a Capfile and a config/deploy.rb

    file • deploy.rb is by convention; we can move the contents to the Capfile if it bothers you • Capfile is necessary and proper; loads capistrano plugins
  35. set  :application,  "set  your  application  name  here" set  :repository,  

     "set  your  repository  location  here" set  :scm,  :subversion #  Or:  `accurev`,  `bzr`,  `cvs`,  `darcs`,  `git`,  `mercurial`,  `perforce`,  `subversion`  or  `none` role  :web,  “your  web-­‐server  here”                                                    #  Your  HTTP  server,  Apache/etc role  :app,  “your  app-­‐server  here”                                                    #  This  may  be  the  same  as  your  `Web`  server role  :db,    “your  primary  db-­‐server  here”,  :primary  =>  true  #  This  is  where  Rails  migrations  will  run role  :db,    “your  slave  db-­‐server  here” ➘ ➘ ➘ ➘ <3 Perforce CakePHP is cool too Cause we’re all on failover servers, right? milliondollarapp.com deploy.rb
  36. CUSTOMIZABLE • Set your own SCM, deploy paths, even callbacks

    • Define custom namespaces and tasks • Override core functionality
  37. ENVIRONMENT HANDLING ##  Available  Environments task  :production  do    server

                               $config[“servers”][“prod”][“server”],  :web,  :god    set  :application,      $config[“servers”][“prod”][“application”]    set  :deploy_to,          $config[“servers”][“prod”][“deploy_to”]    set  :branch,                :master end task  :staging  do    role  :web,                    $config[“servers”][“dev”][“server”]    set  :application,      $config[“servers”][“dev”][“application”]    set  :deploy_to,          $config[“servers”][“dev”][“deploy_to”]    set  :branch,                ENV[‘branch’]  if  ENV.has_key?(‘branch’)  &&  ENV[‘branch’]  =~  /[\w_-­‐]+/i end
  38. CUSTOM TASKS ##  Tasks  involving  assets namespace  :asset  do  

     desc  "Clears  assets"    task  :clear  do        run  "cd  #{app_dir}  &&  ../cake/console/cake  -­‐app  #{app_dir}  asset_compress  clear"    end    desc  "Builds  all  assets"    task  :build  do        run  "cd  #{app_dir}  &&  ../cake/console/cake  -­‐app  #{app_dir}  asset_compress  build"    end    desc  "Builds  ini  assets"    task  :build_ini  do        run  "cd  #{app_dir}  &&  ../cake/console/cake  -­‐app  #{app_dir}  asset_compress  build_ini"    end    desc  "Rebuilds  assets"    task  :rebuild  do        run  "cd  #{app_dir}  &&  ../cake/console/cake  -­‐app  #{app_dir}  asset_compress  clear"        run  "cd  #{app_dir}  &&  ../cake/console/cake  -­‐app  #{app_dir}  asset_compress  build"    end end

  40. CAVEATS • Path to Cake Core may be incorrect -

    use -app flag • Takes some initial setup • Behaves funky with multiple concurrent deploys • Potentially slow with large deploys • Will murder your datacenter if deploying to hundreds of servers
  41. CLAP Props to Michael D’Auria, Sysadmin extraordinaire

  42. LINKS • CFEngine: • Puppet: http://puppetlabs.com • Chef: http://opscode.com/chef •

    CakePHP Chef Cookbooks: http://bit.ly/cakechef • Capistrano: http://capistranorb.com