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

Deployments for beginners - PHP[world]

Michael Heap
November 16, 2016

Deployments for beginners - PHP[world]

Deploying an application means different things to different people. It may be as simple as running `git pull` on a server, or as complex as building RPMs and deploying to a canary set of servers. This talk covers both ends of the spectrum and the points in between. We’ll outline several tried and tested deployment methodologies that everyone can use, whether you’re working with a simple WordPress site or a dozen micro-services.

Michael Heap

November 16, 2016
Tweet

More Decks by Michael Heap

Other Decks in Technology

Transcript

  1. @mheap at #phpworld
    Beginners guide
    to deployments

    View Slide

  2. @mheap
    Let’s talk deployment

    View Slide

  3. @mheap
    Your deploys should be as boring,
    straightforward, and stress-free as
    possible.
    - Zach Holman
    (https://zachholman.com/posts/deploying-software)

    View Slide

  4. @mheap
    How do you deploy?

    View Slide

  5. @mheap
    Edit on the server?

    View Slide

  6. @mheap
    FTP?

    View Slide

  7. @mheap
    git pull?

    View Slide

  8. @mheap
    Third party deployment?

    View Slide

  9. @mheap
    Deployment script?

    View Slide

  10. @mheap
    OS packages?

    View Slide

  11. @mheap
    These are all valid
    ways to deploy

    View Slide

  12. @mheap
    Deployment for beginners

    View Slide

  13. @mheap
    Your deploys should be as boring,
    straightforward, and stress-free as
    possible.
    - Zach Holman
    (https://zachholman.com/posts/deploying-software)

    View Slide

  14. @mheap
    1. What is a deployment?
    2. Option A: External tools
    3. Option B: Internal tools
    4. Option C: System packages
    5. Option D: Blue / Green deployments
    6. Option E: Immutable infrastructure
    7. Deployment techniques
    8. Summary

    View Slide

  15. @mheap
    What is a deployment?

    View Slide

  16. @mheap
    Code

    View Slide

  17. @mheap
    Dependencies

    View Slide

  18. @mheap
    Configuration

    View Slide

  19. @mheap
    Database Migrations

    View Slide

  20. @mheap
    Other Migrations

    View Slide

  21. @mheap
    Assets

    View Slide

  22. @mheap
    Post Install Tasks

    View Slide

  23. @mheap
    We’re aiming for…

    View Slide

  24. @mheap
    Your deploys should be as boring,
    straightforward, and stress-free as
    possible.
    - Zach Holman
    (https://zachholman.com/posts/deploying-software)

    View Slide

  25. @mheap
    Our Codebase

    View Slide

  26. @mheap
    Simple to do list application

    View Slide

  27. @mheap
    Composer
    Silex
    Doctrine Migrations

    View Slide

  28. @mheap
    Time to deploy!

    View Slide

  29. @mheap
    Option A: External tool

    View Slide

  30. @mheap
    @mheap

    View Slide

  31. @mheap
    @mheap

    View Slide

  32. @mheap
    @mheap

    View Slide

  33. @mheap
    @mheap

    View Slide

  34. @mheap
    @mheap

    View Slide

  35. @mheap
    @mheap

    View Slide

  36. @mheap
    @mheap

    View Slide

  37. @mheap
    @mheap

    View Slide

  38. @mheap
    @mheap

    View Slide

  39. @mheap
    @mheap

    View Slide

  40. @mheap
    Useful tools
    Beanstalkapp
    DeployHQ
    Laravel Forge

    View Slide

  41. @mheap
    1. Easy setup
    2. One-click deployments
    3. Environment support
    4. Can only deploy from repo
    1. Files copied one by one
    2. Composer run on server
    3. No build steps
    4. Their way, or the highway
    5. Can’t deploy if provider is
    offline
    Pros Cons

    View Slide

  42. @mheap
    Option B: Internal tool

    View Slide

  43. @mheap
    @mheap

    View Slide

  44. @mheap
    $ gem install capistrano

    View Slide

  45. @mheap
    $ cap install
    => mkdir -p config/deploy
    => create config/deploy.rb
    => create config/deploy/staging.rb
    => create config/deploy/production.rb
    => mkdir -p lib/capistrano/tasks
    => create Capfile
    => Capified

    View Slide

  46. @mheap
    $ cat config/deploy.rb
    lock '3.6.1'
    set :application, 'silex_todo'
    set :repo_url, '[email protected]:mheap/fake-todo-app.git'
    set :deploy_to, '/var/www/todo'

    View Slide

  47. @mheap
    $ cat config/deploy/production.rb
    server 'todo.example.com', user: 'deploy', roles: %w{app db}

    View Slide

  48. @mheap
    $ cap production deploy
    00:00 git:wrapper
    01 mkdir -p /tmp
    02 chmod 700 /tmp/git-ssh-silex_todo-production-michael.sh
    00:07 git:check
    01 git ls-remote --heads [email protected]:mheap/silex-todo-demo.git
    00:08 deploy:check:directories
    01 mkdir -p /var/www/todo/shared /var/www/todo/releases
    00:08 git:clone
    01 git clone --mirror [email protected]:mheap/silex-todo-demo.git /var/www/todo/repo
    01 Cloning into bare repository '/var/www/todo/repo'...
    00:10 git:update
    01 git remote update --prune
    01 Fetching origin
    00:11 git:create_release
    01 mkdir -p /var/www/todo/releases/20161106090926
    02 git archive master | tar -x -f - -C /var/www/todo/releases/20161106090926
    00:12 git:set_current_revision
    01 echo "6cc1b6cbc827e205b24d0d599ea7b667a3ec5ca0" >> REVISION
    00:12 deploy:symlink:release
    01 ln -s /var/www/todo/releases/20161106090926 /var/www/todo/releases/current
    02 mv /var/www/todo/releases/current /var/www/todo
    00:12 deploy:log_revision
    01 echo "Branch master (at 6cc1b6cbc827e205b24d0d599ea7b667a3ec5ca0) deployed as
    release 20161106090926 by michael" >> /var/www/todo/revisions.log

    View Slide

  49. @mheap
    $ cap production deploy
    Generate and upload deployment script
    Clone repo
    Generate archive from repo
    Untar archive into releases folder
    Symlink current folder to the latest release

    View Slide

  50. @mheap
    $ gem install capistrano-composer
    In Capfile:
    require 'capistrano/composer'

    View Slide

  51. @mheap
    $ cap production deploy
    00:18 composer:run
    01 composer install --no-dev --prefer-dist --no-interaction --
    quiet --optimize-autoloader
    ✔ 01 [email protected] 1.023s

    View Slide

  52. @mheap
    lib/capistrano/tasks/database_tasks.rake:
    namespace :database do
    desc 'migrate database'
    task :migrate do
    on roles(:db) do
    execute "cd #{release_path} && ./vendor/bin/
    doctrine-migrations migrations:migrate --db-configuration
    config/db-config.php --configuration config/migrations.yml"
    end
    end
    end

    View Slide

  53. @mheap
    lib/capistrano/tasks/database_tasks.rake:
    namespace :database do
    desc 'migrate database'
    task :migrate do
    on roles(:db) do
    execute "cd #{release_path} && ./vendor/bin/
    doctrine-migrations migrations:migrate --db-configuration
    config/db-config.php --configuration config/migrations.yml"
    end
    end
    end

    View Slide

  54. @mheap
    lib/capistrano/tasks/database_tasks.rake:
    namespace :database do
    desc 'migrate database'
    task :migrate do
    on roles(:db) do
    execute "cd #{release_path} && ./vendor/bin/
    doctrine-migrations migrations:migrate --db-configuration
    config/db-config.php --configuration config/migrations.yml"
    end
    end
    end

    View Slide

  55. @mheap
    lib/capistrano/tasks/database_tasks.rake:
    namespace :database do
    desc 'migrate database'
    task :migrate do
    on roles(:db) do
    execute "cd #{release_path} && ./vendor/bin/
    doctrine-migrations migrations:migrate --db-configuration
    config/db-config.php --configuration config/migrations.yml"
    end
    end
    end

    View Slide

  56. @mheap
    lib/capistrano/tasks/database_tasks.rake:
    namespace :database do
    desc 'migrate database'
    task :migrate do
    on roles(:db) do
    execute "cd #{release_path} && ./vendor/bin/
    doctrine-migrations migrations:migrate --db-configuration
    config/db-config.php --configuration config/migrations.yml"
    end
    end
    end

    View Slide

  57. @mheap
    Capfile:
    after "composer:install", "database:migrate"

    View Slide

  58. @mheap
    $ cap production deploy
    00:22 database:migrate
    01 cd #{release_path} && ./vendor/bin/doctrine-migrations
    migrations:migrate —db-co…
    ✔ 01 [email protected] 0.812s

    View Slide

  59. @mheap
    @mheap

    View Slide

  60. @mheap
    Useful tools
    Capistrano
    Webistrano
    Rocketeer
    Ansible

    View Slide

  61. @mheap
    1. One-click deployments
    2. Environment support
    3. Can only deploy from repo
    4. Internal solution
    5. Atomic deploys
    6. Rollback support
    1. Learning curve
    2. Composer run on server
    3. No build steps
    4. Probably want to use
    Bundler to manage versions
    Pros Cons

    View Slide

  62. @mheap
    Option C: System Packages

    View Slide

  63. @mheap
    $ apt-get install todo
    $ yum install todo
    $ pacman -S todo

    View Slide

  64. @mheap
    @mheap

    View Slide

  65. @mheap
    @mheap

    View Slide

  66. @mheap
    .
    !"" resources
    !"" src
    # !"" application
    # # !"" controller
    # # # $"" IndexController.php
    # # !"" model
    # # # $"" User.php
    # # $"" view
    # # $"" show-user.php
    # !"" composer.json
    # !"" composer.lock
    # !"" config
    # # !"" mappings.json
    # # $"" targets.json
    # $"" public
    # $"" index.php
    $"" test

    View Slide

  67. @mheap
    .
    !"" resources
    !"" src
    # !"" application
    # # !"" controller
    # # # $"" IndexController.php
    # # !"" model
    # # # $"" User.php
    # # $"" view
    # # $"" show-user.php
    # !"" composer.json
    # !"" composer.lock
    # !"" config
    # # !"" mappings.json
    # # $"" targets.json
    # $"" public
    # $"" index.php
    $"" test
    $ fpm -s dir -t rpm -n todo

    View Slide

  68. @mheap
    .
    !"" resources
    !"" src
    # !"" application
    # # !"" controller
    # # # $"" IndexController.php
    # # !"" model
    # # # $"" User.php
    # # $"" view
    # # $"" show-user.php
    # !"" composer.json
    # !"" composer.lock
    # !"" config
    # # !"" mappings.json
    # # $"" targets.json
    # $"" public
    # $"" index.php
    $"" test
    $ fpm -s dir -t rpm -n todo \
    src/=/var/www/todo \
    src/config/=/etc/todo

    View Slide

  69. @mheap
    .
    !"" resources
    !"" src
    # !"" application
    # # !"" controller
    # # # $"" IndexController.php
    # # !"" model
    # # # $"" User.php
    # # $"" view
    # # $"" show-user.php
    # !"" composer.json
    # !"" composer.lock
    # !"" config
    # # !"" mappings.json
    # # $"" targets.json
    # $"" public
    # $"" index.php
    $"" test
    $ fpm -s dir -t rpm --config-files /etc \
    -n todo \
    src/=/var/www/todo \
    src/config/=/etc/todo

    View Slide

  70. @mheap
    .
    !"" resources
    !"" src
    # !"" application
    # # !"" controller
    # # # $"" IndexController.php
    # # !"" model
    # # # $"" User.php
    # # $"" view
    # # $"" show-user.php
    # !"" composer.json
    # !"" composer.lock
    # !"" config
    # # !"" mappings.json
    # # $"" targets.json
    # $"" public
    # $"" index.php
    $"" test
    $ fpm -s dir -t rpm --config-files /etc \
    --exclude "var/www/todo/config*" \
    -n todo \
    src/=/var/www/todo \
    src/config/=/etc/todo

    View Slide

  71. @mheap
    $ fpm -s dir -t rpm --config-files /etc --exclude
    "var/www/todo/config*" -n todo src/=/var/
    www/todo src/config/=/etc/todo
    => Created package
    {:path=>"todo-1.0-1.x86_64.rpm"}

    View Slide

  72. @mheap
    Continous Integration

    View Slide

  73. @mheap
    What is
    Continous Integration?

    View Slide

  74. @mheap
    Use it to
    run tests

    View Slide

  75. @mheap
    Use it to
    composer install

    View Slide

  76. @mheap
    Use it to
    mitigate risk

    View Slide

  77. @mheap
    Use it to
    build on identical platforms

    View Slide

  78. @mheap
    Use it to
    package your application

    View Slide

  79. @mheap
    Use it to
    deploy to production

    View Slide

  80. @mheap
    Use it to
    AUTOMATE THINGS

    View Slide

  81. @mheap
    @mheap

    View Slide

  82. @mheap
    Option C: System Packages

    View Slide

  83. @mheap
    $ apt-get install todo
    $ yum install todo
    $ pacman -S todo

    View Slide

  84. @mheap
    Almost

    View Slide

  85. @mheap
    Database migrations

    View Slide

  86. @mheap
    $ fpm -s dir -t rpm --config-files /etc --exclude
    "var/www/todo/config*" -n todo src/=/var/
    www/todo src/config/=/etc/todo
    => Created package
    {:path=>"todo-1.0-1.x86_64.rpm"}

    View Slide

  87. @mheap
    $ fpm -s dir -t rpm --config-files /etc --exclude
    "var/www/todo/config*" -n todo
    --after-install /path/to/script src/=/var/www/
    todo src/config/=/etc/todo
    => Created package
    {:path=>"todo-1.0-1.x86_64.rpm"}

    View Slide

  88. @mheap
    Useful tools
    FPM
    Jenkins
    RPM / Deb / Pkg

    View Slide

  89. @mheap
    Releases are
    immutable

    View Slide

  90. @mheap
    1. Atomic releases
    2. Build on system tools
    3. Proper build toolchain
    4. Signed builds
    5. Easy upgrade/rollback
    6. Immutable
    1. Steep learning curve
    2. Need to run package repo
    3. Ideal to run CI system
    Pros Cons

    View Slide

  91. @mheap
    Option D: Blue / Green

    View Slide

  92. @mheap
    Load
    Balancer

    View Slide

  93. @mheap
    Load
    Balancer

    View Slide

  94. @mheap
    Shared databases

    View Slide

  95. @mheap
    Single database

    View Slide

  96. @mheap
    Server maintenance

    View Slide

  97. @mheap
    Shameless Plug

    View Slide

  98. @mheap
    Infrastructure level

    View Slide

  99. @mheap
    Useful tools
    Puppet / Chef / Ansible
    HAProxy

    View Slide

  100. @mheap
    1. Low risk deployments
    2. Test on production systems
    3. Easy changeover
    1. Can be expensive
    2. Databases are hard
    3. More moving parts to
    manage
    Pros Cons

    View Slide

  101. @mheap
    Option E: Immutable

    View Slide

  102. @mheap
    1 0 0
    1 0 1
    Load
    Balancer

    View Slide

  103. @mheap
    1 0 1
    Load
    Balancer

    View Slide

  104. @mheap
    1 0 1
    Load
    Balancer 1 0 2
    1 1 0

    View Slide

  105. @mheap
    Load
    Balancer
    1 0 1
    1 0 2
    1 1 0

    View Slide

  106. @mheap
    Load
    Balancer 1 0 2
    1 1 0

    View Slide

  107. @mheap
    Why immutable?

    View Slide

  108. @mheap
    Load
    Balancer
    1 0 0
    1 0 1

    View Slide

  109. @mheap
    1 0 0
    1 0 1
    Load
    Balancer

    View Slide

  110. @mheap
    1 0 0
    Load
    Balancer

    View Slide

  111. @mheap
    1 0 0
    Load
    Balancer
    1 0 2

    View Slide

  112. @mheap
    Useful tools
    Puppet / Chef / Ansible
    Packer
    Cloud providers

    View Slide

  113. @mheap
    1. Known environment
    2. Test 2+ releases at once
    3. Easy changeover
    4. Truly atomic releases
    1. Cost
    2. Slow to build
    3. Database sync
    Pros Cons

    View Slide

  114. @mheap
    Deployment techniques

    View Slide

  115. @mheap
    Build (at least) daily
    (even better if it’s automated)

    View Slide

  116. @mheap
    Announce releases

    View Slide

  117. @mheap
    Staggered Releases

    View Slide

  118. @mheap
    Canary deploys

    View Slide

  119. @mheap
    Go / No Go

    View Slide

  120. @mheap
    Containers

    View Slide

  121. @mheap
    Chatops

    View Slide

  122. @mheap
    Summary

    View Slide

  123. @mheap
    Automate your deployment

    View Slide

  124. @mheap
    Local builds

    View Slide

  125. @mheap
    Immutable releases

    View Slide

  126. @mheap
    Think about deployment
    before you write any code

    View Slide

  127. @mheap
    The three strikes rule

    View Slide

  128. @mheap
    Make it a single command

    View Slide

  129. @mheap
    Your deploys should be as boring,
    straightforward, and stress-free as
    possible.
    - Zach Holman
    (https://zachholman.com/posts/deploying-software)

    View Slide

  130. @mheap at #phpworld
    https://joind.in/
    18696
    Michael Heap
    @mheap
    [email protected]

    View Slide