SlideShare a Scribd company logo
1 of 73
Download to read offline
A Scalable Rails app
  Deployed in 60
      seconds




                       1
Ben Scheirman



• Director of Development at ChaiONE
• Microsoft MVP, ASP Insider
• Certified ScrumMaster
• Former .NET Ninja, now Rails/iPhone
  aficionado
                                        2
Ben Scheirman




• ...not affiliated with Heroku

                                   3
So you have a fantastic app?




                               4
5
6
7
7
7
7
7
7
8
8
9
10
11
x 1,000?
           11
12
x 10,000?
            12
writes


reads




         13
writes


reads




         x 1,000,000?
                        13
14
On-Demand
        15
# Users by time of day
400



300



200



100



 0
 12 AM 3AM 6AM 9AM 12PM 3PM 6PM 9PM 12AM



                                           16
# Users by time of day
400



300



200



100



 0
 12 AM 3AM 6AM 9AM 12PM 3PM 6PM 9PM 12AM



                                           16
# Users by time of day
400



300



200



100



 0
 12 AM 3AM 6AM 9AM 12PM 3PM 6PM 9PM 12AM

        Only need massive scale from 9am - 9pm

                                                 16
Expected Users For PR Campaign
900



675



450



225



  0
  Mar 1 Mar 15 Apr 1 Apr 15 May 1 May 15 Jun 1 Jun 2



                                                       17
Expected Users For PR Campaign
900



675



450



225



  0
  Mar 1 Mar 15 Apr 1 Apr 15 May 1 May 15 Jun 1 Jun 2



                                                       17
SCALE




        18
19
Awesome Shredder Art by Dan Barret

                                20
gem install heroku
             Awesome Shredder Art by Dan Barret

                                             20
• Platform as a service for Rack-based apps
• Scale easily
• Great workflow
• Free to start / Friendly Pricing
• Complete command-line API
                                              21
Deploy a rails app in 5 steps


             git init
             git add .
             git commit -m “My First Commit”
             heroku create
             git push heroku master
Creating morning-summer-18..... done
Created http://morning-summer-18.heroku.com/ | git@heroku.com:morning-summer-18.git




                                                                                      22
Deploy a rails app in 5 steps


             git init
             git add .
             git commit -m “My First Commit”
             heroku create
             git push heroku master
Creating morning-summer-18..... done
Created http://morning-summer-18.heroku.com/ | git@heroku.com:morning-summer-18.git




                                        LET THAT SOAK IN...

                                                                                      22
Using git for deployment is f***ing
              GENIUS




                                      23
Technology




             • Amazon Web Services
             • Caching w/ Varnish
             • Debian Linux
             • Erlang Routing Mesh
             • Nginx
             • PostgreSQL
                                     24
25
How Heroku Scales




                    26
How Heroku Scales
  or WTF is a Dyno?




                      26
How Heroku Scales
  or WTF is a Dyno?




                      26
How Heroku Scales
  or WTF is a Dyno?




                      26
How Heroku Scales




                    27
How Heroku Scales




                    27
How Heroku Scales




                    27
When to add dynos




• Increasing response times
• “Backlog Too Deep” Error
                                           28
Always Measure




• New Relic RPM
• Apache Bench



                                   29
Heroku Tips



         • Multiple Heroku apps for Test, Staging,
              Production
         • Learn the awesome-ness of Taps
         • Heroku logs
         • Heroku Console
         • Useful addons: New Relic, Exceptional
                                                     30
Backups




          31
Coping with the Free Single Bundle
  task :backup do
    bundle_name = "my-backup"
    heroku_app = ENV['app']

      def wait_for_response_text(text)
        heroku_app = ENV['app'] #lame, I know
        begin
          puts "."
          bundles = `heroku bundles --app #{heroku_app}`
        end while bundles.match(text).nil?
      end

      #check for existing bundle
      bundles = `heroku bundles --app #{heroku_app}`
      unless bundles.match /has no bundles/
          `heroku bundles:destroy #{bundle_name} --app #{heroku_app}`
          wait_for_response_text 'has no bundles'
      end

      puts "Capture bundle #{bundle_name}..."
      `heroku bundles:capture #{bundle_name} --app #{heroku_app}`
      wait_for_response_text "complete"

      puts "Downloading bundle..."
      `heroku bundles:download #{bundle_name} --app #{heroku_app}`
      timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp
      new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz"
      mkdir "backups" unless File.exists? "backups"

      `mv #{heroku_app}.tar.gz #{new_path}`
      puts "Bundle saved to #{new_path}" end
end
                                                                        32
Coping with the Free Single Bundle
  task :backup do
    bundle_name = "my-backup"
    heroku_app = ENV['app']

      def wait_for_response_text(text)
        heroku_app = ENV['app'] #lame, I know
        begin
          puts "."
          bundles = `heroku bundles --app #{heroku_app}`
        end while bundles.match(text).nil?
      end

      #check for existing bundle
      bundles = `heroku bundles --app #{heroku_app}`
      unless bundles.match /has no bundles/
          `heroku bundles:destroy #{bundle_name} --app #{heroku_app}`
          wait_for_response_text 'has no bundles'
      end

      puts "Capture bundle #{bundle_name}..."
      `heroku bundles:capture #{bundle_name} --app #{heroku_app}`
      wait_for_response_text "complete"

      puts "Downloading bundle..."
      `heroku bundles:download #{bundle_name} --app #{heroku_app}`
      timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp
      new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz"
      mkdir "backups" unless File.exists? "backups"

      `mv #{heroku_app}.tar.gz #{new_path}`
      puts "Bundle saved to #{new_path}" end
end
                                                                        33
Coping with the Free Single Bundle
  task :backup do
    bundle_name = "my-backup"
    heroku_app = ENV['app']

      def wait_for_response_text(text)
        heroku_app = ENV['app'] #lame, I know
        begin
          puts "."
          bundles = `heroku bundles --app #{heroku_app}`
        end while bundles.match(text).nil?
      end

      #check for existing bundle
      bundles = `heroku bundles --app #{heroku_app}`
      unless bundles.match /has no bundles/
          `heroku bundles:destroy #{bundle_name} --app #{heroku_app}`
          wait_for_response_text 'has no bundles'
      end

      puts "Capture bundle #{bundle_name}..."
      `heroku bundles:capture #{bundle_name} --app #{heroku_app}`
      wait_for_response_text "complete"

      puts "Downloading bundle..."
      `heroku bundles:download #{bundle_name} --app #{heroku_app}`
      timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp
      new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz"
      mkdir "backups" unless File.exists? "backups"

      `mv #{heroku_app}.tar.gz #{new_path}`
      puts "Bundle saved to #{new_path}" end
end
                                                                        34
Coping with the Free Single Bundle
  task :backup do
    bundle_name = "my-backup"
    heroku_app = ENV['app']

      def wait_for_response_text(text)
        heroku_app = ENV['app'] #lame, I know
        begin
          puts "."
          bundles = `heroku bundles --app #{heroku_app}`
        end while bundles.match(text).nil?
      end

      #check for existing bundle
      bundles = `heroku bundles --app #{heroku_app}`
      unless bundles.match /has no bundles/
          `heroku bundles:destroy #{bundle_name} --app #{heroku_app}`
          wait_for_response_text 'has no bundles'
      end

      puts "Capture bundle #{bundle_name}..."
      `heroku bundles:capture #{bundle_name} --app #{heroku_app}`
      wait_for_response_text "complete"

      puts "Downloading bundle..."
      `heroku bundles:download #{bundle_name} --app #{heroku_app}`
      timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp
      new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz"
      mkdir "backups" unless File.exists? "backups"

      `mv #{heroku_app}.tar.gz #{new_path}`
      puts "Bundle saved to #{new_path}" end
end
                                                                        35
Coping with the Free Single Bundle
  task :backup do
    bundle_name = "my-backup"
    heroku_app = ENV['app']

      def wait_for_response_text(text)
        heroku_app = ENV['app'] #lame, I know
        begin
          puts "."
          bundles = `heroku bundles --app #{heroku_app}`
        end while bundles.match(text).nil?
      end

      #check for existing bundle
      bundles = `heroku bundles --app #{heroku_app}`
      unless bundles.match /has no bundles/
          `heroku bundles:destroy #{bundle_name} --app #{heroku_app}`
          wait_for_response_text 'has no bundles'
      end

      puts "Capture bundle #{bundle_name}..."
      `heroku bundles:capture #{bundle_name} --app #{heroku_app}`
      wait_for_response_text "complete"

      puts "Downloading bundle..."
      `heroku bundles:download #{bundle_name} --app #{heroku_app}`
      timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp
      new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz"
      mkdir "backups" unless File.exists? "backups"

      `mv #{heroku_app}.tar.gz #{new_path}`
      puts "Bundle saved to #{new_path}" end
end
                                                                        36
Coping with the Free Single Bundle
  task :backup do
    bundle_name = "my-backup"
    heroku_app = ENV['app']

      def wait_for_response_text(text)
        heroku_app = ENV['app'] #lame, I know
        begin
          puts "."
          bundles = `heroku bundles --app #{heroku_app}`
        end while bundles.match(text).nil?
      end

      #check for existing bundle
      bundles = `heroku bundles --app #{heroku_app}`
      unless bundles.match /has no bundles/
          `heroku bundles:destroy #{bundle_name} --app #{heroku_app}`
          wait_for_response_text 'has no bundles'
      end

      puts "Capture bundle #{bundle_name}..."
      `heroku bundles:capture #{bundle_name} --app #{heroku_app}`
      wait_for_response_text "complete"

      puts "Downloading bundle..."
      `heroku bundles:download #{bundle_name} --app #{heroku_app}`
      timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp
      new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz"
      mkdir "backups" unless File.exists? "backups"

      `mv #{heroku_app}.tar.gz #{new_path}`
      puts "Bundle saved to #{new_path}" end
end
                                                                        37
Coping with the Free Single Bundle
  task :backup do
    bundle_name = "my-backup"
    heroku_app = ENV['app']

      def wait_for_response_text(text)
        heroku_app = ENV['app'] #lame, I know
        begin
          puts "."
          bundles = `heroku bundles --app #{heroku_app}`
        end while bundles.match(text).nil?
      end

      #check for existing bundle
      bundles = `heroku bundles --app #{heroku_app}`
      unless bundles.match /has no bundles/
          `heroku bundles:destroy #{bundle_name} --app #{heroku_app}`
          wait_for_response_text 'has no bundles'
      end

      puts "Capture bundle #{bundle_name}..."
      `heroku bundles:capture #{bundle_name} --app #{heroku_app}`
      wait_for_response_text "complete"

      puts "Downloading bundle..."
      `heroku bundles:download #{bundle_name} --app #{heroku_app}`
      timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp
      new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz"
      mkdir "backups" unless File.exists? "backups"

      `mv #{heroku_app}.tar.gz #{new_path}`
      puts "Bundle saved to #{new_path}" end
end
                                                                        38
Coping with the Free Single Bundle
  task :backup do
    bundle_name = "my-backup"
    heroku_app = ENV['app']

      def wait_for_response_text(text)
        heroku_app = ENV['app'] #lame, I know
        begin
          puts "."
          bundles = `heroku bundles --app #{heroku_app}`
        end while bundles.match(text).nil?
      end

      #check for existing bundle
      bundles = `heroku bundles --app #{heroku_app}`
      unless bundles.match /has no bundles/
          `heroku bundles:destroy #{bundle_name} --app #{heroku_app}`
          wait_for_response_text 'has no bundles'
      end

      puts "Capture bundle #{bundle_name}..."
      `heroku bundles:capture #{bundle_name} --app #{heroku_app}`
      wait_for_response_text "complete"

      puts "Downloading bundle..."
      `heroku bundles:download #{bundle_name} --app #{heroku_app}`
      timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp
      new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz"
      mkdir "backups" unless File.exists? "backups"

      `mv #{heroku_app}.tar.gz #{new_path}`
      puts "Bundle saved to #{new_path}" end
end
                                                                        39
One-button Deployments
task :deploy do

  heroku_app = ENV['app']

  heroku_config = Hash.new
  Rake::Task["heroku:backup"].invoke

  puts "Turning maintenance on..."
  puts "** " + `heroku maintenance:on --app #{heroku_app}`
  sleep 15 #maintenance mode causes your slug to be recompiled

  puts "Pushing changes to heroku..."
  puts "** " + `git push #{git_remotes[heroku_app]} master`

  puts "Migrating heroku databases..."
  puts "** " + `heroku rake db:migrate --app #{heroku_app}`

  puts "Setting up config variables..."
  heroku_config.each_pair do |k, v|
    puts "** " + `heroku config:add #{k.to_s.upcase}=#{v}`
  end

  puts "Turning maintenance mode off"
  puts "** " + `heroku maintenance:off --app #{heroku_app}`

  puts "DEPLOYMENT DONE!"
end


                                                                 40
Delayed Jobs




               41
Delayed Jobs


def send_bulk_emails

      BulkEmailSender.send_a_ton
      flash[:notice] => "Ok we sent them"

end




                                                           41
Delayed Jobs


def send_bulk_emails

      BulkEmailSender.send_a_ton
      flash[:notice] => "Ok we sent them"

end




                          def send_bulk_emails

                                BulkEmailSender.send_later(:send_a_ton)
                                flash[:notice] => "Ok we sent them"

                          end


                                                                      41
Delayed Jobs




               42
Delayed Jobs


> gem install delayed_job
> rails g delayed_job
> rake db:migrate




                                           42
Delayed Jobs


> gem install delayed_job
> rails g delayed_job
> rake db:migrate




                        > heroku workers 1
                           simple-snow-68 now running 1 worker
                        > heroku workers +1
                           simple-snow-68 now running 2 workers



                                                                  42
Delayed Jobs




               43
Delayed Jobs



$0.05 per hour / worker
(even when it's not processing Jobs)




                                                      43
Delayed Jobs



$0.05 per hour / worker
(even when it's not processing Jobs)




                     http://github.com/pedro/delayed_job/commit/
                     09d7657e1fc7d25072e6c5e73ede20d6e1185eac

                     http://bit.ly/9Qokff



                                                                   43
Delayed Jobs
Pedro's Fork / auto-scale branch




                               44
Delayed Jobs
             Pedro's Fork / auto-scale branch



//lib/delayed/job.rb
def after_create
  Manager.scale_up if self.class.auto_scale &&
    Manager.qty == 0
end

//lib/delayed/worker.rb
Manager.scale_down if count.zero? &&
  Job.auto_scale &&
  Job.count == 0




                                                 44
• Read-only file system
 • some gems don’t work
 • File uploads?
 • Temp Directory
• SSL, memcached, Full-text-search expensive
• Bound-by Amazon’s SLA
                                               45
contact = {

! :blog => http://flux88.com,
!
! :twitter => @subdigital,
!
! :email => ben@scheirman.com

}

                                46
47

More Related Content

What's hot

Dependencies Managers in C/C++. Using stdcpp 2014
Dependencies Managers in C/C++. Using stdcpp 2014Dependencies Managers in C/C++. Using stdcpp 2014
Dependencies Managers in C/C++. Using stdcpp 2014biicode
 
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & Hadoop
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & HadoopPuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & Hadoop
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & HadoopWalter Heck
 
PuppetCamp SEA 1 - Puppet Deployment at OnApp
PuppetCamp SEA 1 - Puppet Deployment  at OnAppPuppetCamp SEA 1 - Puppet Deployment  at OnApp
PuppetCamp SEA 1 - Puppet Deployment at OnAppWalter Heck
 
PuppetCamp SEA 1 - Use of Puppet
PuppetCamp SEA 1 - Use of PuppetPuppetCamp SEA 1 - Use of Puppet
PuppetCamp SEA 1 - Use of PuppetWalter Heck
 
DevOps(3) : Ansible - (MOSG)
DevOps(3) : Ansible - (MOSG)DevOps(3) : Ansible - (MOSG)
DevOps(3) : Ansible - (MOSG)Soshi Nemoto
 
DevOps(4) : Ansible(2) - (MOSG)
DevOps(4) : Ansible(2) - (MOSG)DevOps(4) : Ansible(2) - (MOSG)
DevOps(4) : Ansible(2) - (MOSG)Soshi Nemoto
 
Puppet and Apache CloudStack
Puppet and Apache CloudStackPuppet and Apache CloudStack
Puppet and Apache CloudStackPuppet
 
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....BDD - Buzzword Driven Development - Build the next cool app for fun and for.....
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....Alessandro Cinelli (cirpo)
 
Development with Ansible & VMs
Development with Ansible & VMsDevelopment with Ansible & VMs
Development with Ansible & VMsJeff Schenck
 
From Dev to DevOps - FOSDEM 2012
From Dev to DevOps - FOSDEM 2012From Dev to DevOps - FOSDEM 2012
From Dev to DevOps - FOSDEM 2012Carlos Sanchez
 
Augeas, swiss knife resources for your puppet tree
Augeas, swiss knife resources for your puppet treeAugeas, swiss knife resources for your puppet tree
Augeas, swiss knife resources for your puppet treeJulien Pivotto
 
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013Carlos Sanchez
 
Getting Started With CFEngine - Updated Version
Getting Started With CFEngine - Updated VersionGetting Started With CFEngine - Updated Version
Getting Started With CFEngine - Updated VersionCFEngine
 
Effective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 DevelopersEffective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 DevelopersMarcin Chwedziak
 
Puppet for Java developers - JavaZone NO 2012
Puppet for Java developers - JavaZone NO 2012Puppet for Java developers - JavaZone NO 2012
Puppet for Java developers - JavaZone NO 2012Carlos Sanchez
 
From Dev to DevOps - Apache Barcamp Spain 2011
From Dev to DevOps - Apache Barcamp Spain 2011From Dev to DevOps - Apache Barcamp Spain 2011
From Dev to DevOps - Apache Barcamp Spain 2011Carlos Sanchez
 
Building and Testing from Scratch a Puppet Environment with Docker - PuppetCo...
Building and Testing from Scratch a Puppet Environment with Docker - PuppetCo...Building and Testing from Scratch a Puppet Environment with Docker - PuppetCo...
Building and Testing from Scratch a Puppet Environment with Docker - PuppetCo...Puppet
 
Create Development and Production Environments with Vagrant
Create Development and Production Environments with VagrantCreate Development and Production Environments with Vagrant
Create Development and Production Environments with VagrantBrian Hogan
 
Vagrant for real (codemotion rome 2016)
Vagrant for real (codemotion rome 2016)Vagrant for real (codemotion rome 2016)
Vagrant for real (codemotion rome 2016)Michele Orselli
 
Instruction: dev environment
Instruction: dev environmentInstruction: dev environment
Instruction: dev environmentSoshi Nemoto
 

What's hot (20)

Dependencies Managers in C/C++. Using stdcpp 2014
Dependencies Managers in C/C++. Using stdcpp 2014Dependencies Managers in C/C++. Using stdcpp 2014
Dependencies Managers in C/C++. Using stdcpp 2014
 
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & Hadoop
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & HadoopPuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & Hadoop
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & Hadoop
 
PuppetCamp SEA 1 - Puppet Deployment at OnApp
PuppetCamp SEA 1 - Puppet Deployment  at OnAppPuppetCamp SEA 1 - Puppet Deployment  at OnApp
PuppetCamp SEA 1 - Puppet Deployment at OnApp
 
PuppetCamp SEA 1 - Use of Puppet
PuppetCamp SEA 1 - Use of PuppetPuppetCamp SEA 1 - Use of Puppet
PuppetCamp SEA 1 - Use of Puppet
 
DevOps(3) : Ansible - (MOSG)
DevOps(3) : Ansible - (MOSG)DevOps(3) : Ansible - (MOSG)
DevOps(3) : Ansible - (MOSG)
 
DevOps(4) : Ansible(2) - (MOSG)
DevOps(4) : Ansible(2) - (MOSG)DevOps(4) : Ansible(2) - (MOSG)
DevOps(4) : Ansible(2) - (MOSG)
 
Puppet and Apache CloudStack
Puppet and Apache CloudStackPuppet and Apache CloudStack
Puppet and Apache CloudStack
 
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....BDD - Buzzword Driven Development - Build the next cool app for fun and for.....
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....
 
Development with Ansible & VMs
Development with Ansible & VMsDevelopment with Ansible & VMs
Development with Ansible & VMs
 
From Dev to DevOps - FOSDEM 2012
From Dev to DevOps - FOSDEM 2012From Dev to DevOps - FOSDEM 2012
From Dev to DevOps - FOSDEM 2012
 
Augeas, swiss knife resources for your puppet tree
Augeas, swiss knife resources for your puppet treeAugeas, swiss knife resources for your puppet tree
Augeas, swiss knife resources for your puppet tree
 
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013
 
Getting Started With CFEngine - Updated Version
Getting Started With CFEngine - Updated VersionGetting Started With CFEngine - Updated Version
Getting Started With CFEngine - Updated Version
 
Effective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 DevelopersEffective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 Developers
 
Puppet for Java developers - JavaZone NO 2012
Puppet for Java developers - JavaZone NO 2012Puppet for Java developers - JavaZone NO 2012
Puppet for Java developers - JavaZone NO 2012
 
From Dev to DevOps - Apache Barcamp Spain 2011
From Dev to DevOps - Apache Barcamp Spain 2011From Dev to DevOps - Apache Barcamp Spain 2011
From Dev to DevOps - Apache Barcamp Spain 2011
 
Building and Testing from Scratch a Puppet Environment with Docker - PuppetCo...
Building and Testing from Scratch a Puppet Environment with Docker - PuppetCo...Building and Testing from Scratch a Puppet Environment with Docker - PuppetCo...
Building and Testing from Scratch a Puppet Environment with Docker - PuppetCo...
 
Create Development and Production Environments with Vagrant
Create Development and Production Environments with VagrantCreate Development and Production Environments with Vagrant
Create Development and Production Environments with Vagrant
 
Vagrant for real (codemotion rome 2016)
Vagrant for real (codemotion rome 2016)Vagrant for real (codemotion rome 2016)
Vagrant for real (codemotion rome 2016)
 
Instruction: dev environment
Instruction: dev environmentInstruction: dev environment
Instruction: dev environment
 

Viewers also liked

Path: Why you need another social media app
Path: Why you need another social media appPath: Why you need another social media app
Path: Why you need another social media appPeriscope
 
Salesforce.com Partner Meetup - New York -10/18/12
Salesforce.com Partner Meetup - New York -10/18/12 Salesforce.com Partner Meetup - New York -10/18/12
Salesforce.com Partner Meetup - New York -10/18/12 Salesforce Partners
 
Dyno cycling behavior of Heroku
Dyno cycling behavior of HerokuDyno cycling behavior of Heroku
Dyno cycling behavior of HerokuShunji Konishi
 
herokuでfacebookアプリを作ったお話
herokuでfacebookアプリを作ったお話herokuでfacebookアプリを作ったお話
herokuでfacebookアプリを作ったお話Naoto Koshikawa
 
Codeacademy's Linda Liukas at Heroku's Waza 2013: Code is Everyone's Business
Codeacademy's Linda Liukas at Heroku's Waza 2013: Code is Everyone's BusinessCodeacademy's Linda Liukas at Heroku's Waza 2013: Code is Everyone's Business
Codeacademy's Linda Liukas at Heroku's Waza 2013: Code is Everyone's BusinessHeroku
 
Social Design :: Social Network Design
Social Design :: Social Network DesignSocial Design :: Social Network Design
Social Design :: Social Network DesignJaume Teixi
 
Developing a Real Time Ad-Server on Heroku
Developing a Real Time Ad-Server on HerokuDeveloping a Real Time Ad-Server on Heroku
Developing a Real Time Ad-Server on HerokuSalesforce Developers
 
Mattt Thompson at Heroku's Waza 2013: Mobile is not Different
Mattt Thompson at Heroku's Waza 2013: Mobile is not Different Mattt Thompson at Heroku's Waza 2013: Mobile is not Different
Mattt Thompson at Heroku's Waza 2013: Mobile is not Different Heroku
 
Getting Started with Heroku
Getting Started with HerokuGetting Started with Heroku
Getting Started with HerokuLaunchAny
 

Viewers also liked (11)

Path: Why you need another social media app
Path: Why you need another social media appPath: Why you need another social media app
Path: Why you need another social media app
 
Salesforce.com Partner Meetup - New York -10/18/12
Salesforce.com Partner Meetup - New York -10/18/12 Salesforce.com Partner Meetup - New York -10/18/12
Salesforce.com Partner Meetup - New York -10/18/12
 
Dyno cycling behavior of Heroku
Dyno cycling behavior of HerokuDyno cycling behavior of Heroku
Dyno cycling behavior of Heroku
 
herokuでfacebookアプリを作ったお話
herokuでfacebookアプリを作ったお話herokuでfacebookアプリを作ったお話
herokuでfacebookアプリを作ったお話
 
Codeacademy's Linda Liukas at Heroku's Waza 2013: Code is Everyone's Business
Codeacademy's Linda Liukas at Heroku's Waza 2013: Code is Everyone's BusinessCodeacademy's Linda Liukas at Heroku's Waza 2013: Code is Everyone's Business
Codeacademy's Linda Liukas at Heroku's Waza 2013: Code is Everyone's Business
 
Social Design :: Social Network Design
Social Design :: Social Network DesignSocial Design :: Social Network Design
Social Design :: Social Network Design
 
Developing a Real Time Ad-Server on Heroku
Developing a Real Time Ad-Server on HerokuDeveloping a Real Time Ad-Server on Heroku
Developing a Real Time Ad-Server on Heroku
 
Continuous Deploy
Continuous DeployContinuous Deploy
Continuous Deploy
 
Mattt Thompson at Heroku's Waza 2013: Mobile is not Different
Mattt Thompson at Heroku's Waza 2013: Mobile is not Different Mattt Thompson at Heroku's Waza 2013: Mobile is not Different
Mattt Thompson at Heroku's Waza 2013: Mobile is not Different
 
Getting Started with Heroku
Getting Started with HerokuGetting Started with Heroku
Getting Started with Heroku
 
ταξίδι στη γλώσσα
ταξίδι στη γλώσσαταξίδι στη γλώσσα
ταξίδι στη γλώσσα
 

Similar to A Scalable Rails App Deployed in 60 Seconds

LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경
LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경
LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경Mintak Son
 
Virtual Environment and Web development using Django
Virtual Environment and Web development using DjangoVirtual Environment and Web development using Django
Virtual Environment and Web development using DjangoSunil kumar Mohanty
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slidesharetomcopeland
 
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)ZFConf Conference
 
OpenSource ToolChain for the Hybrid Cloud
OpenSource ToolChain for the Hybrid CloudOpenSource ToolChain for the Hybrid Cloud
OpenSource ToolChain for the Hybrid CloudIsaac Christoffersen
 
2015 DockerCon Using Docker in production at bity.com
2015 DockerCon Using Docker in production at bity.com2015 DockerCon Using Docker in production at bity.com
2015 DockerCon Using Docker in production at bity.comMathieu Buffenoir
 
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...POSSCON
 
DockerCon EU 2015: Trading Bitcoin with Docker
DockerCon EU 2015: Trading Bitcoin with DockerDockerCon EU 2015: Trading Bitcoin with Docker
DockerCon EU 2015: Trading Bitcoin with DockerDocker, Inc.
 
Symfony Deployments on Heroku
Symfony Deployments on HerokuSymfony Deployments on Heroku
Symfony Deployments on HerokuStefan Adolf
 
Hosting Your Own OTA Update Service
Hosting Your Own OTA Update ServiceHosting Your Own OTA Update Service
Hosting Your Own OTA Update ServiceQuinlan Jung
 
How I hack on puppet modules
How I hack on puppet modulesHow I hack on puppet modules
How I hack on puppet modulesKris Buytaert
 
From Arm to Z: Building, Shipping, and Running a Multi-platform Docker Swarm ...
From Arm to Z: Building, Shipping, and Running a Multi-platform Docker Swarm ...From Arm to Z: Building, Shipping, and Running a Multi-platform Docker Swarm ...
From Arm to Z: Building, Shipping, and Running a Multi-platform Docker Swarm ...Docker, Inc.
 
A to Z of a Multi-platform Docker Swarm: Building, Shipping, and Running Mult...
A to Z of a Multi-platform Docker Swarm: Building, Shipping, and Running Mult...A to Z of a Multi-platform Docker Swarm: Building, Shipping, and Running Mult...
A to Z of a Multi-platform Docker Swarm: Building, Shipping, and Running Mult...Christy Norman
 
Dockercon EU 2014
Dockercon EU 2014Dockercon EU 2014
Dockercon EU 2014Rafe Colton
 
The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...
The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...
The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...Docker, Inc.
 
From Zero to Application Delivery with NixOS
From Zero to Application Delivery with NixOSFrom Zero to Application Delivery with NixOS
From Zero to Application Delivery with NixOSSusan Potter
 
Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3Clinton Dreisbach
 
Create ReactJS Component & publish as npm package
Create ReactJS Component & publish as npm packageCreate ReactJS Component & publish as npm package
Create ReactJS Component & publish as npm packageAndrii Lundiak
 
Using Prometheus to monitor your build pipelines
Using Prometheus to monitor your build pipelinesUsing Prometheus to monitor your build pipelines
Using Prometheus to monitor your build pipelinesLander Van den Bulcke
 

Similar to A Scalable Rails App Deployed in 60 Seconds (20)

LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경
LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경
LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경
 
Virtual Environment and Web development using Django
Virtual Environment and Web development using DjangoVirtual Environment and Web development using Django
Virtual Environment and Web development using Django
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshare
 
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
 
OpenSource ToolChain for the Hybrid Cloud
OpenSource ToolChain for the Hybrid CloudOpenSource ToolChain for the Hybrid Cloud
OpenSource ToolChain for the Hybrid Cloud
 
2015 DockerCon Using Docker in production at bity.com
2015 DockerCon Using Docker in production at bity.com2015 DockerCon Using Docker in production at bity.com
2015 DockerCon Using Docker in production at bity.com
 
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...
 
DockerCon EU 2015: Trading Bitcoin with Docker
DockerCon EU 2015: Trading Bitcoin with DockerDockerCon EU 2015: Trading Bitcoin with Docker
DockerCon EU 2015: Trading Bitcoin with Docker
 
Symfony Deployments on Heroku
Symfony Deployments on HerokuSymfony Deployments on Heroku
Symfony Deployments on Heroku
 
Hosting Your Own OTA Update Service
Hosting Your Own OTA Update ServiceHosting Your Own OTA Update Service
Hosting Your Own OTA Update Service
 
How I hack on puppet modules
How I hack on puppet modulesHow I hack on puppet modules
How I hack on puppet modules
 
From Arm to Z: Building, Shipping, and Running a Multi-platform Docker Swarm ...
From Arm to Z: Building, Shipping, and Running a Multi-platform Docker Swarm ...From Arm to Z: Building, Shipping, and Running a Multi-platform Docker Swarm ...
From Arm to Z: Building, Shipping, and Running a Multi-platform Docker Swarm ...
 
A to Z of a Multi-platform Docker Swarm: Building, Shipping, and Running Mult...
A to Z of a Multi-platform Docker Swarm: Building, Shipping, and Running Mult...A to Z of a Multi-platform Docker Swarm: Building, Shipping, and Running Mult...
A to Z of a Multi-platform Docker Swarm: Building, Shipping, and Running Mult...
 
Dockercon EU 2014
Dockercon EU 2014Dockercon EU 2014
Dockercon EU 2014
 
The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...
The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...
The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...
 
Git::Hooks
Git::HooksGit::Hooks
Git::Hooks
 
From Zero to Application Delivery with NixOS
From Zero to Application Delivery with NixOSFrom Zero to Application Delivery with NixOS
From Zero to Application Delivery with NixOS
 
Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3
 
Create ReactJS Component & publish as npm package
Create ReactJS Component & publish as npm packageCreate ReactJS Component & publish as npm package
Create ReactJS Component & publish as npm package
 
Using Prometheus to monitor your build pipelines
Using Prometheus to monitor your build pipelinesUsing Prometheus to monitor your build pipelines
Using Prometheus to monitor your build pipelines
 

More from Ben Scheirman

Effective iOS Network Programming Techniques
Effective iOS Network Programming TechniquesEffective iOS Network Programming Techniques
Effective iOS Network Programming TechniquesBen Scheirman
 
Objective-C & iPhone for .NET Developers
Objective-C & iPhone for .NET DevelopersObjective-C & iPhone for .NET Developers
Objective-C & iPhone for .NET DevelopersBen Scheirman
 
iPhone for .NET Developers
iPhone for .NET DevelopersiPhone for .NET Developers
iPhone for .NET DevelopersBen Scheirman
 
Reasons To Love Ruby
Reasons To Love RubyReasons To Love Ruby
Reasons To Love RubyBen Scheirman
 

More from Ben Scheirman (6)

Meet Git
Meet GitMeet Git
Meet Git
 
Effective iOS Network Programming Techniques
Effective iOS Network Programming TechniquesEffective iOS Network Programming Techniques
Effective iOS Network Programming Techniques
 
Objective-C & iPhone for .NET Developers
Objective-C & iPhone for .NET DevelopersObjective-C & iPhone for .NET Developers
Objective-C & iPhone for .NET Developers
 
iPhone for .NET Developers
iPhone for .NET DevelopersiPhone for .NET Developers
iPhone for .NET Developers
 
SQLite Techniques
SQLite TechniquesSQLite Techniques
SQLite Techniques
 
Reasons To Love Ruby
Reasons To Love RubyReasons To Love Ruby
Reasons To Love Ruby
 

Recently uploaded

[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Scott Andery
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditSkynet Technologies
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...panagenda
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationKnoldus Inc.
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 

Recently uploaded (20)

[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance Audit
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog Presentation
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 

A Scalable Rails App Deployed in 60 Seconds

  • 1. A Scalable Rails app Deployed in 60 seconds 1
  • 2. Ben Scheirman • Director of Development at ChaiONE • Microsoft MVP, ASP Insider • Certified ScrumMaster • Former .NET Ninja, now Rails/iPhone aficionado 2
  • 3. Ben Scheirman • ...not affiliated with Heroku 3
  • 4. So you have a fantastic app? 4
  • 5. 5
  • 6. 6
  • 7. 7
  • 8. 7
  • 9. 7
  • 10. 7
  • 11. 7
  • 12. 7
  • 13. 8
  • 14. 8
  • 15. 9
  • 16. 10
  • 17. 11
  • 18. x 1,000? 11
  • 19. 12
  • 20. x 10,000? 12
  • 22. writes reads x 1,000,000? 13
  • 23. 14
  • 24. On-Demand 15
  • 25. # Users by time of day 400 300 200 100 0 12 AM 3AM 6AM 9AM 12PM 3PM 6PM 9PM 12AM 16
  • 26. # Users by time of day 400 300 200 100 0 12 AM 3AM 6AM 9AM 12PM 3PM 6PM 9PM 12AM 16
  • 27. # Users by time of day 400 300 200 100 0 12 AM 3AM 6AM 9AM 12PM 3PM 6PM 9PM 12AM Only need massive scale from 9am - 9pm 16
  • 28. Expected Users For PR Campaign 900 675 450 225 0 Mar 1 Mar 15 Apr 1 Apr 15 May 1 May 15 Jun 1 Jun 2 17
  • 29. Expected Users For PR Campaign 900 675 450 225 0 Mar 1 Mar 15 Apr 1 Apr 15 May 1 May 15 Jun 1 Jun 2 17
  • 30. SCALE 18
  • 31. 19
  • 32. Awesome Shredder Art by Dan Barret 20
  • 33. gem install heroku Awesome Shredder Art by Dan Barret 20
  • 34. • Platform as a service for Rack-based apps • Scale easily • Great workflow • Free to start / Friendly Pricing • Complete command-line API 21
  • 35. Deploy a rails app in 5 steps git init git add . git commit -m “My First Commit” heroku create git push heroku master Creating morning-summer-18..... done Created http://morning-summer-18.heroku.com/ | git@heroku.com:morning-summer-18.git 22
  • 36. Deploy a rails app in 5 steps git init git add . git commit -m “My First Commit” heroku create git push heroku master Creating morning-summer-18..... done Created http://morning-summer-18.heroku.com/ | git@heroku.com:morning-summer-18.git LET THAT SOAK IN... 22
  • 37. Using git for deployment is f***ing GENIUS 23
  • 38. Technology • Amazon Web Services • Caching w/ Varnish • Debian Linux • Erlang Routing Mesh • Nginx • PostgreSQL 24
  • 39. 25
  • 41. How Heroku Scales or WTF is a Dyno? 26
  • 42. How Heroku Scales or WTF is a Dyno? 26
  • 43. How Heroku Scales or WTF is a Dyno? 26
  • 47. When to add dynos • Increasing response times • “Backlog Too Deep” Error 28
  • 48. Always Measure • New Relic RPM • Apache Bench 29
  • 49. Heroku Tips • Multiple Heroku apps for Test, Staging, Production • Learn the awesome-ness of Taps • Heroku logs • Heroku Console • Useful addons: New Relic, Exceptional 30
  • 50. Backups 31
  • 51. Coping with the Free Single Bundle task :backup do bundle_name = "my-backup" heroku_app = ENV['app'] def wait_for_response_text(text) heroku_app = ENV['app'] #lame, I know begin puts "." bundles = `heroku bundles --app #{heroku_app}` end while bundles.match(text).nil? end #check for existing bundle bundles = `heroku bundles --app #{heroku_app}` unless bundles.match /has no bundles/ `heroku bundles:destroy #{bundle_name} --app #{heroku_app}` wait_for_response_text 'has no bundles' end puts "Capture bundle #{bundle_name}..." `heroku bundles:capture #{bundle_name} --app #{heroku_app}` wait_for_response_text "complete" puts "Downloading bundle..." `heroku bundles:download #{bundle_name} --app #{heroku_app}` timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz" mkdir "backups" unless File.exists? "backups" `mv #{heroku_app}.tar.gz #{new_path}` puts "Bundle saved to #{new_path}" end end 32
  • 52. Coping with the Free Single Bundle task :backup do bundle_name = "my-backup" heroku_app = ENV['app'] def wait_for_response_text(text) heroku_app = ENV['app'] #lame, I know begin puts "." bundles = `heroku bundles --app #{heroku_app}` end while bundles.match(text).nil? end #check for existing bundle bundles = `heroku bundles --app #{heroku_app}` unless bundles.match /has no bundles/ `heroku bundles:destroy #{bundle_name} --app #{heroku_app}` wait_for_response_text 'has no bundles' end puts "Capture bundle #{bundle_name}..." `heroku bundles:capture #{bundle_name} --app #{heroku_app}` wait_for_response_text "complete" puts "Downloading bundle..." `heroku bundles:download #{bundle_name} --app #{heroku_app}` timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz" mkdir "backups" unless File.exists? "backups" `mv #{heroku_app}.tar.gz #{new_path}` puts "Bundle saved to #{new_path}" end end 33
  • 53. Coping with the Free Single Bundle task :backup do bundle_name = "my-backup" heroku_app = ENV['app'] def wait_for_response_text(text) heroku_app = ENV['app'] #lame, I know begin puts "." bundles = `heroku bundles --app #{heroku_app}` end while bundles.match(text).nil? end #check for existing bundle bundles = `heroku bundles --app #{heroku_app}` unless bundles.match /has no bundles/ `heroku bundles:destroy #{bundle_name} --app #{heroku_app}` wait_for_response_text 'has no bundles' end puts "Capture bundle #{bundle_name}..." `heroku bundles:capture #{bundle_name} --app #{heroku_app}` wait_for_response_text "complete" puts "Downloading bundle..." `heroku bundles:download #{bundle_name} --app #{heroku_app}` timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz" mkdir "backups" unless File.exists? "backups" `mv #{heroku_app}.tar.gz #{new_path}` puts "Bundle saved to #{new_path}" end end 34
  • 54. Coping with the Free Single Bundle task :backup do bundle_name = "my-backup" heroku_app = ENV['app'] def wait_for_response_text(text) heroku_app = ENV['app'] #lame, I know begin puts "." bundles = `heroku bundles --app #{heroku_app}` end while bundles.match(text).nil? end #check for existing bundle bundles = `heroku bundles --app #{heroku_app}` unless bundles.match /has no bundles/ `heroku bundles:destroy #{bundle_name} --app #{heroku_app}` wait_for_response_text 'has no bundles' end puts "Capture bundle #{bundle_name}..." `heroku bundles:capture #{bundle_name} --app #{heroku_app}` wait_for_response_text "complete" puts "Downloading bundle..." `heroku bundles:download #{bundle_name} --app #{heroku_app}` timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz" mkdir "backups" unless File.exists? "backups" `mv #{heroku_app}.tar.gz #{new_path}` puts "Bundle saved to #{new_path}" end end 35
  • 55. Coping with the Free Single Bundle task :backup do bundle_name = "my-backup" heroku_app = ENV['app'] def wait_for_response_text(text) heroku_app = ENV['app'] #lame, I know begin puts "." bundles = `heroku bundles --app #{heroku_app}` end while bundles.match(text).nil? end #check for existing bundle bundles = `heroku bundles --app #{heroku_app}` unless bundles.match /has no bundles/ `heroku bundles:destroy #{bundle_name} --app #{heroku_app}` wait_for_response_text 'has no bundles' end puts "Capture bundle #{bundle_name}..." `heroku bundles:capture #{bundle_name} --app #{heroku_app}` wait_for_response_text "complete" puts "Downloading bundle..." `heroku bundles:download #{bundle_name} --app #{heroku_app}` timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz" mkdir "backups" unless File.exists? "backups" `mv #{heroku_app}.tar.gz #{new_path}` puts "Bundle saved to #{new_path}" end end 36
  • 56. Coping with the Free Single Bundle task :backup do bundle_name = "my-backup" heroku_app = ENV['app'] def wait_for_response_text(text) heroku_app = ENV['app'] #lame, I know begin puts "." bundles = `heroku bundles --app #{heroku_app}` end while bundles.match(text).nil? end #check for existing bundle bundles = `heroku bundles --app #{heroku_app}` unless bundles.match /has no bundles/ `heroku bundles:destroy #{bundle_name} --app #{heroku_app}` wait_for_response_text 'has no bundles' end puts "Capture bundle #{bundle_name}..." `heroku bundles:capture #{bundle_name} --app #{heroku_app}` wait_for_response_text "complete" puts "Downloading bundle..." `heroku bundles:download #{bundle_name} --app #{heroku_app}` timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz" mkdir "backups" unless File.exists? "backups" `mv #{heroku_app}.tar.gz #{new_path}` puts "Bundle saved to #{new_path}" end end 37
  • 57. Coping with the Free Single Bundle task :backup do bundle_name = "my-backup" heroku_app = ENV['app'] def wait_for_response_text(text) heroku_app = ENV['app'] #lame, I know begin puts "." bundles = `heroku bundles --app #{heroku_app}` end while bundles.match(text).nil? end #check for existing bundle bundles = `heroku bundles --app #{heroku_app}` unless bundles.match /has no bundles/ `heroku bundles:destroy #{bundle_name} --app #{heroku_app}` wait_for_response_text 'has no bundles' end puts "Capture bundle #{bundle_name}..." `heroku bundles:capture #{bundle_name} --app #{heroku_app}` wait_for_response_text "complete" puts "Downloading bundle..." `heroku bundles:download #{bundle_name} --app #{heroku_app}` timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz" mkdir "backups" unless File.exists? "backups" `mv #{heroku_app}.tar.gz #{new_path}` puts "Bundle saved to #{new_path}" end end 38
  • 58. Coping with the Free Single Bundle task :backup do bundle_name = "my-backup" heroku_app = ENV['app'] def wait_for_response_text(text) heroku_app = ENV['app'] #lame, I know begin puts "." bundles = `heroku bundles --app #{heroku_app}` end while bundles.match(text).nil? end #check for existing bundle bundles = `heroku bundles --app #{heroku_app}` unless bundles.match /has no bundles/ `heroku bundles:destroy #{bundle_name} --app #{heroku_app}` wait_for_response_text 'has no bundles' end puts "Capture bundle #{bundle_name}..." `heroku bundles:capture #{bundle_name} --app #{heroku_app}` wait_for_response_text "complete" puts "Downloading bundle..." `heroku bundles:download #{bundle_name} --app #{heroku_app}` timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz" mkdir "backups" unless File.exists? "backups" `mv #{heroku_app}.tar.gz #{new_path}` puts "Bundle saved to #{new_path}" end end 39
  • 59. One-button Deployments task :deploy do heroku_app = ENV['app'] heroku_config = Hash.new Rake::Task["heroku:backup"].invoke puts "Turning maintenance on..." puts "** " + `heroku maintenance:on --app #{heroku_app}` sleep 15 #maintenance mode causes your slug to be recompiled puts "Pushing changes to heroku..." puts "** " + `git push #{git_remotes[heroku_app]} master` puts "Migrating heroku databases..." puts "** " + `heroku rake db:migrate --app #{heroku_app}` puts "Setting up config variables..." heroku_config.each_pair do |k, v| puts "** " + `heroku config:add #{k.to_s.upcase}=#{v}` end puts "Turning maintenance mode off" puts "** " + `heroku maintenance:off --app #{heroku_app}` puts "DEPLOYMENT DONE!" end 40
  • 61. Delayed Jobs def send_bulk_emails BulkEmailSender.send_a_ton flash[:notice] => "Ok we sent them" end 41
  • 62. Delayed Jobs def send_bulk_emails BulkEmailSender.send_a_ton flash[:notice] => "Ok we sent them" end def send_bulk_emails BulkEmailSender.send_later(:send_a_ton) flash[:notice] => "Ok we sent them" end 41
  • 64. Delayed Jobs > gem install delayed_job > rails g delayed_job > rake db:migrate 42
  • 65. Delayed Jobs > gem install delayed_job > rails g delayed_job > rake db:migrate > heroku workers 1 simple-snow-68 now running 1 worker > heroku workers +1 simple-snow-68 now running 2 workers 42
  • 67. Delayed Jobs $0.05 per hour / worker (even when it's not processing Jobs) 43
  • 68. Delayed Jobs $0.05 per hour / worker (even when it's not processing Jobs) http://github.com/pedro/delayed_job/commit/ 09d7657e1fc7d25072e6c5e73ede20d6e1185eac http://bit.ly/9Qokff 43
  • 69. Delayed Jobs Pedro's Fork / auto-scale branch 44
  • 70. Delayed Jobs Pedro's Fork / auto-scale branch //lib/delayed/job.rb def after_create Manager.scale_up if self.class.auto_scale && Manager.qty == 0 end //lib/delayed/worker.rb Manager.scale_down if count.zero? && Job.auto_scale && Job.count == 0 44
  • 71. • Read-only file system • some gems don’t work • File uploads? • Temp Directory • SSL, memcached, Full-text-search expensive • Bound-by Amazon’s SLA 45
  • 72. contact = { ! :blog => http://flux88.com, ! ! :twitter => @subdigital, ! ! :email => ben@scheirman.com } 46
  • 73. 47