Plack + Carton: deployment made simple and awesome

Plack + Carton: deployment made simple and awesome

at PerlMova and YAPC::Russia 2012

B2d653d5d663e750a2cd57bfbc9b727f?s=128

Tatsuhiko Miyagawa

May 12, 2012
Tweet

Transcript

  1. Plack + Carton deployment simple & awesome Tatsuhiko Miyagawa Perl

    Mova / YAPC::Russia 2012 Saturday, May 12, 12
  2. привет Saturday, May 12, 12

  3. Me • Tatsuhiko Miyagawa • CPAN: MIYAGAWA • github.com/miyagawa •

    Twitter @miyagawa • Lives in San Francisco, CA Saturday, May 12, 12
  4. Saturday, May 12, 12

  5. Saturday, May 12, 12

  6. Saturday, May 12, 12

  7. Saturday, May 12, 12

  8. Saturday, May 12, 12

  9. Saturday, May 12, 12

  10. Saturday, May 12, 12

  11. Saturday, May 12, 12

  12. Saturday, May 12, 12

  13. My Software Saturday, May 12, 12

  14. Saturday, May 12, 12

  15. Saturday, May 12, 12

  16. • PSGI • Plack • cpanminus • carton Saturday, May

    12, 12
  17. PSGI Saturday, May 12, 12

  18. Perl Server Gateway Interface Saturday, May 12, 12

  19. Inspired by WSGI, Rack Saturday, May 12, 12

  20. WSGI (PEP-333) Saturday, May 12, 12

  21. Saturday, May 12, 12

  22. #  WSGI def  hello(environ,  start_response):    start_response(“200  OK”,  [  

         (‘Content-­‐Type’,  ‘text/plain’)    ])    return  [“Hello  World”] Saturday, May 12, 12
  23. WSGI • Django • Bottle • CherryPy • Tornado •

    Pylons • Flask • mod_wsgi • Paste • gunicorn • uWSGI • wsgiref • Google AppEngine Saturday, May 12, 12
  24. WSGI WSGI middleware Django Bottle Flask Tornado Apache lighttpd nginx

    mod_wsgi wsgi handlers GAE Saturday, May 12, 12
  25. Rack Saturday, May 12, 12

  26. Saturday, May 12, 12

  27. #  Rack class  Hello    def  call(env)      

     return  [              200,              {  “Content-­‐Type”  =>  ”text/plain”  },                [“Hello  World”]        ]    end end Saturday, May 12, 12
  28. Rack • Rails • Merb • Sinatra • Camping •

    Ramaze • etc. • Unicorn • Thin • Mongrel • Rainbows! • Phusion Passenger • Heroku Saturday, May 12, 12
  29. Rack Rack middleware Rails Merb Sinatra Ramaze Apache lighttpd Thin

    Unicorn Rack handlers Mongrel Saturday, May 12, 12
  30. PSGI Perl Web Server Gateway Interface Saturday, May 12, 12

  31. Interface Saturday, May 12, 12

  32. #  WSGI def  hello(environ,  start_response):    start_response(“200  OK”,  [  

         (‘Content-­‐Type’,  ‘text/plain’)    ])    return  [“Hello  World”] Saturday, May 12, 12
  33. #  Rack class  Hello    def  call(env)      

     return  [              200,              {  “Content-­‐Type”  =>  ”text/plain”  },                [“Hello  World”]        ]    end end Saturday, May 12, 12
  34. #  PSGI my  $app  =  sub  {      

     my  $env  =  shift;        return  [                  200,                [  ‘Content-­‐Type’,  ‘text/plain’  ],                [  ‘Hello  World’  ],        ]; }; Saturday, May 12, 12
  35. That’s it. Saturday, May 12, 12

  36. #  PSGI my  $app  =  sub  {      

     my  $env  =  shift;        return  [                  200,                [  ‘Content-­‐Type’,  ‘text/plain’  ],                [  ‘Hello  World’  ],        ]; }; Saturday, May 12, 12
  37. Now you’ve got a PSGI application. Saturday, May 12, 12

  38. PSGI makes it so simple to: Saturday, May 12, 12

  39. Write a new Perl web app & framework Saturday, May

    12, 12
  40. Write a new Perl web server Saturday, May 12, 12

  41. CGI::Application Apache IIS lighttpd CGI.pm CGI fastcgi mod_perl Jifty Mason

    Catalyst Mason::CGIHandler Catalyst::Engine nginx HTTP::Server ::Simple Saturday, May 12, 12
  42. PSGI Plack::Middleware Catalyst CGI::App Jifty Dancer Apache lighttpd HTTP::Server::PSGI Twiggy

    Starman Plack::Handler::* (CGI, FCGI, Apache) Saturday, May 12, 12
  43. #  Catalyst use  MyApp; MyApp-­‐>setup_engine(‘PSGI’); my  $app  =  sub  {

     MyApp-­‐>run(@_)  }; #  $app  is  a  PSGI  app! Saturday, May 12, 12
  44. #  Jifty use  MyPonyApp; my  $app  =  MyPonyApp-­‐>psgi_app; #  $app

     is  a  PSGI  app! Saturday, May 12, 12
  45. #  Dancer use  Dancer; get  ‘/’  =>  sub  {  

         “Hello  World”; }; dance;  #  returns  a  PSGI  app! Saturday, May 12, 12
  46. #  Mojolicious::Lite use  Mojolicious::Lite; get  ‘/:name’  =>  sub  {  

         my  $self  =  shift;        $self-­‐>render_text(‘Hello!’); }; app-­‐>start;  #  returns  PSGI  app Saturday, May 12, 12
  47. #  Web::Simple use  Web::Simple  ‘MyApp’; package  MyApp; dispatch  {  

     sub(GET)  {        [  200,  [...],  [  ‘Hello’  ]  ];    } }; my  $app  =  MyApp-­‐>as_psgi; #  $app  is  a  PSGI  app! Saturday, May 12, 12
  48. Saturday, May 12, 12

  49. Recap: PSGI • Inspired by Python, Ruby • Very simple

    • Code ref, hash ref, array ref • adapted by many frameworks and businesses Saturday, May 12, 12
  50. cpanminus Saturday, May 12, 12

  51. Saturday, May 12, 12

  52. Dead easy to install Sane defaults Ultra-lightweight Saturday, May 12,

    12
  53. >  curl  -­‐L  cpanmin.us  |\    perl  -­‐  App::cpanminus Saturday,

    May 12, 12
  54. Saturday, May 12, 12

  55. -­‐-­‐installdeps Saturday, May 12, 12

  56. PSGI/Plack convention for writing apps Saturday, May 12, 12

  57. cpanm --installdeps convention for installing deps Saturday, May 12, 12

  58. PSGI/Plack + cpanminus = ? Saturday, May 12, 12

  59. Saturday, May 12, 12

  60. Step 1: Write your app in PSGI (with PSGI-compatible framework)

    Saturday, May 12, 12
  61. Step 2: Maintain dependencies in git with Makefile.PL/Build.PL Saturday, May

    12, 12
  62. Step 3: Run your code on the cloud via git

    push! Saturday, May 12, 12
  63. Saturday, May 12, 12

  64. http://showmetheco.de/articles/2011/8/three-perl-cloud-hosting-platforms.html Saturday, May 12, 12

  65. Heroku buildpacks • judofyr/perloku • miyagawa/heroku-buildpack-perl • lstoll/heroku-buildpack-perl Saturday, May

    12, 12
  66. Saturday, May 12, 12

  67. Saturday, May 12, 12

  68. Saturday, May 12, 12

  69. DIY https://github.com/dagolden/perl-chef Saturday, May 12, 12

  70. Recap • PSGI: web app standard • cpanm: dependencies installation

    • PSGI + cpanm => Deploy to the cloud! Saturday, May 12, 12
  71. Problems Saturday, May 12, 12

  72. Step 2: Maintain dependencies in git with Makefile.PL/Build.PL Saturday, May

    12, 12
  73. Makefile.PL Saturday, May 12, 12

  74. use  ExtUtils::MakeMaker; WriteMakefile(    NAME  =>  ‘MyModule’,    VERSION  =>

     ‘1.22’,    PREREQ_PM  =>  {        ‘JSON’  =>  0,        ‘Hash::MultiValue’  =>  ‘0.11’,    }, ); Saturday, May 12, 12
  75. use  Module::Build; my  $build  =  Module::Build-­‐>new(    module_name  =>  ‘MyModule’,

       requires  =>  {        ‘JSON’  =>  ‘2.00’,        ‘Hash::MultiValie’  =>  ‘0.20’,    }, ); $build-­‐>create_build_script; Saturday, May 12, 12
  76. use  inc::Module::Install; name  ‘MyApp’; all_from  ‘lib/MyApp.pm’; requires  ‘JSON’,  ‘2.00’; requires

     ‘Hash::MultiValue’  =>  0.10; WriteAll; Saturday, May 12, 12
  77. Problem 1) Lots of boilerplate Saturday, May 12, 12

  78. use  ExtUtils::MakeMaker; WriteMakefile(    NAME  =>  ‘MyModule’,    VERSION  =>

     ‘1.22’,    PREREQ_PM  =>  {        ‘JSON’  =>  0,        ‘Hash::MultiValue’  =>  ‘0.11’,    }, ); Saturday, May 12, 12
  79. use  Module::Build; my  $build  =  Module::Build-­‐>new(    module_name  =>  ‘MyModule’,

       requires  =>  {        ‘JSON’  =>  ‘2.00’,        ‘Hash::MultiValie’  =>  ‘0.20’,    }, ); $build-­‐>create_build_script; Saturday, May 12, 12
  80. use  inc::Module::Install; name  ‘MyApp’; all_from  ‘lib/MyApp.pm’; requires  ‘JSON’,  ‘2.00’; requires

     ‘Hash::MultiValue’  =>  0.10; WriteAll; Saturday, May 12, 12
  81. Bootstrapping inc/Module/Install.pm  in  git configure_requires  META.yml Saturday, May 12, 12

  82. Problem 2) No way to freeze dep versions Saturday, May

    12, 12
  83. ‘MooseX::Foo’  =>  1.0 means MooseX::Foo with 1.0 or newer Saturday,

    May 12, 12
  84. cpanm  -­‐-­‐installdeps Installs the latest version of modules that satisfies

    the requirements Saturday, May 12, 12
  85. What if ... Saturday, May 12, 12

  86. • Jul 2nd: Started working on project • using Web::Framework

    1.1 • Jul 9th: Finished version 1.0 • Jul 10-15th: internal beta, QA • Jul 16th: Deploy to the cloud/production Saturday, May 12, 12
  87. • Jul 2nd: Started working on project • using Web::Framework

    1.1 • Jul 9th: Finished version 1.0 • Jul 10-15th: internal beta, QA • Jul 16th: Web::Framework 1.2 is released • Jul 16th: Deploy to the cloud/production Saturday, May 12, 12
  88. Web::Framework 1.2 broke my code! Saturday, May 12, 12

  89. Saturday, May 12, 12

  90. Makefile.PL Recap • Not so easy to write • Could

    have deps, bootstrapping issue • No way to freeze versions Saturday, May 12, 12
  91. A solution Saturday, May 12, 12

  92. cpanfile  + Carton Saturday, May 12, 12

  93. requires  ‘Plack’,  0.9980; requires  ‘Catalyst’,  ‘>=  5.8,  <  5.9’; conflicts

     ‘MooseX::Foo’,  ‘<  0.10’; on  ‘test’  =>  sub  {        requires  ‘Test::More’,  0.80; }; on  ‘develop’  =>  sub  {        requires  ‘Devel::NYTProf’; }; Saturday, May 12, 12
  94. inspired by: gemfile(5) Saturday, May 12, 12

  95. Backward compatible to: Module::Install(::DSL) Saturday, May 12, 12

  96. Converted to to: CPAN::Meta::Prereqs Saturday, May 12, 12

  97. Toolset Module::CPANfile Module::Install::CPANfile Saturday, May 12, 12

  98. Supported by Dist::Zilla & Carton Saturday, May 12, 12

  99. Carton https://github.com/miyagawa/carton Saturday, May 12, 12

  100. Manages CPAN deps Saturday, May 12, 12

  101. Inspired by... Saturday, May 12, 12

  102. Saturday, May 12, 12

  103. • App-specific local environment • Fast and safe install •

    Dep-tree analysis, including versions • Locking module versions • Easy Redeployment • Single-file, VCS friendly • Safe and easy rollback Saturday, May 12, 12
  104. Local perl environment Using local::lib and cpanm -L Each app

    has an isolated local library path Saturday, May 12, 12
  105. Fast and safe install cpanm 1.5 Saves MYMETA.json and install

    meta info Saturday, May 12, 12
  106. Dep tree analysis Rebuild the dependency tree from meta info

    Checks if anything is missing/superfluous Saturday, May 12, 12
  107. Locking versions Versions are saved in carton.lock including dependencies Saturday,

    May 12, 12
  108. Easy Redeployment Reinstall exactly the same set of modules on

    another prod/development machines. Saturday, May 12, 12
  109. Single-file, VCS friendly You can add carton.lock to git update

    whenever you update modules Saturday, May 12, 12
  110. Safe and easy rollback revert the lock file and redeploy

    Saturday, May 12, 12
  111. DEMO Saturday, May 12, 12

  112. >  cpanm  Carton Saturday, May 12, 12

  113. WARNING It is pre-1.0 beta software, some features are missing

    or not working correctly (yet). Saturday, May 12, 12
  114. TODO / Roadmap • Update specific modules • Make install

    and bundle faster • Inject old versions / patched versions • Install from git SHA Saturday, May 12, 12
  115. Recap • Write app in PSGI/Plack • Specify CPAN dependencies

    with cpanfile • Manage them and deploy with carton • Inspired by Ruby :) Saturday, May 12, 12
  116. github.com/miyagawa/carton irc.perl.org #carton Saturday, May 12, 12

  117. Saturday, May 12, 12

  118. Questions? Saturday, May 12, 12

  119. спасибо! speakerdeck.com/u/miyagawa Saturday, May 12, 12