Slide 1

Slide 1 text

@mheap at #phpworld Beginners guide to deployments

Slide 2

Slide 2 text

@mheap Let’s talk deployment

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

@mheap How do you deploy?

Slide 5

Slide 5 text

@mheap Edit on the server?

Slide 6

Slide 6 text

@mheap FTP?

Slide 7

Slide 7 text

@mheap git pull?

Slide 8

Slide 8 text

@mheap Third party deployment?

Slide 9

Slide 9 text

@mheap Deployment script?

Slide 10

Slide 10 text

@mheap OS packages?

Slide 11

Slide 11 text

@mheap These are all valid ways to deploy

Slide 12

Slide 12 text

@mheap Deployment for beginners

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

@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

Slide 15

Slide 15 text

@mheap What is a deployment?

Slide 16

Slide 16 text

@mheap Code

Slide 17

Slide 17 text

@mheap Dependencies

Slide 18

Slide 18 text

@mheap Configuration

Slide 19

Slide 19 text

@mheap Database Migrations

Slide 20

Slide 20 text

@mheap Other Migrations

Slide 21

Slide 21 text

@mheap Assets

Slide 22

Slide 22 text

@mheap Post Install Tasks

Slide 23

Slide 23 text

@mheap We’re aiming for…

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

@mheap Our Codebase

Slide 26

Slide 26 text

@mheap Simple to do list application

Slide 27

Slide 27 text

@mheap Composer Silex Doctrine Migrations

Slide 28

Slide 28 text

@mheap Time to deploy!

Slide 29

Slide 29 text

@mheap Option A: External tool

Slide 30

Slide 30 text

@mheap @mheap

Slide 31

Slide 31 text

@mheap @mheap

Slide 32

Slide 32 text

@mheap @mheap

Slide 33

Slide 33 text

@mheap @mheap

Slide 34

Slide 34 text

@mheap @mheap

Slide 35

Slide 35 text

@mheap @mheap

Slide 36

Slide 36 text

@mheap @mheap

Slide 37

Slide 37 text

@mheap @mheap

Slide 38

Slide 38 text

@mheap @mheap

Slide 39

Slide 39 text

@mheap @mheap

Slide 40

Slide 40 text

@mheap Useful tools Beanstalkapp DeployHQ Laravel Forge

Slide 41

Slide 41 text

@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

Slide 42

Slide 42 text

@mheap Option B: Internal tool

Slide 43

Slide 43 text

@mheap @mheap

Slide 44

Slide 44 text

@mheap $ gem install capistrano

Slide 45

Slide 45 text

@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

Slide 46

Slide 46 text

@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'

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

@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

Slide 49

Slide 49 text

@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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

@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

Slide 52

Slide 52 text

@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

Slide 53

Slide 53 text

@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

Slide 54

Slide 54 text

@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

Slide 55

Slide 55 text

@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

Slide 56

Slide 56 text

@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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

@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

Slide 59

Slide 59 text

@mheap @mheap

Slide 60

Slide 60 text

@mheap Useful tools Capistrano Webistrano Rocketeer Ansible

Slide 61

Slide 61 text

@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

Slide 62

Slide 62 text

@mheap Option C: System Packages

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

@mheap @mheap

Slide 65

Slide 65 text

@mheap @mheap

Slide 66

Slide 66 text

@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

Slide 67

Slide 67 text

@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

Slide 68

Slide 68 text

@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

Slide 69

Slide 69 text

@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

Slide 70

Slide 70 text

@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

Slide 71

Slide 71 text

@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"}

Slide 72

Slide 72 text

@mheap Continous Integration

Slide 73

Slide 73 text

@mheap What is Continous Integration?

Slide 74

Slide 74 text

@mheap Use it to run tests

Slide 75

Slide 75 text

@mheap Use it to composer install

Slide 76

Slide 76 text

@mheap Use it to mitigate risk

Slide 77

Slide 77 text

@mheap Use it to build on identical platforms

Slide 78

Slide 78 text

@mheap Use it to package your application

Slide 79

Slide 79 text

@mheap Use it to deploy to production

Slide 80

Slide 80 text

@mheap Use it to AUTOMATE THINGS

Slide 81

Slide 81 text

@mheap @mheap

Slide 82

Slide 82 text

@mheap Option C: System Packages

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

@mheap Almost

Slide 85

Slide 85 text

@mheap Database migrations

Slide 86

Slide 86 text

@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"}

Slide 87

Slide 87 text

@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"}

Slide 88

Slide 88 text

@mheap Useful tools FPM Jenkins RPM / Deb / Pkg

Slide 89

Slide 89 text

@mheap Releases are immutable

Slide 90

Slide 90 text

@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

Slide 91

Slide 91 text

@mheap Option D: Blue / Green

Slide 92

Slide 92 text

@mheap Load Balancer

Slide 93

Slide 93 text

@mheap Load Balancer

Slide 94

Slide 94 text

@mheap Shared databases

Slide 95

Slide 95 text

@mheap Single database

Slide 96

Slide 96 text

@mheap Server maintenance

Slide 97

Slide 97 text

@mheap Shameless Plug

Slide 98

Slide 98 text

@mheap Infrastructure level

Slide 99

Slide 99 text

@mheap Useful tools Puppet / Chef / Ansible HAProxy

Slide 100

Slide 100 text

@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

Slide 101

Slide 101 text

@mheap Option E: Immutable

Slide 102

Slide 102 text

@mheap 1 0 0 1 0 1 Load Balancer

Slide 103

Slide 103 text

@mheap 1 0 1 Load Balancer

Slide 104

Slide 104 text

@mheap 1 0 1 Load Balancer 1 0 2 1 1 0

Slide 105

Slide 105 text

@mheap Load Balancer 1 0 1 1 0 2 1 1 0

Slide 106

Slide 106 text

@mheap Load Balancer 1 0 2 1 1 0

Slide 107

Slide 107 text

@mheap Why immutable?

Slide 108

Slide 108 text

@mheap Load Balancer 1 0 0 1 0 1

Slide 109

Slide 109 text

@mheap 1 0 0 1 0 1 Load Balancer

Slide 110

Slide 110 text

@mheap 1 0 0 Load Balancer

Slide 111

Slide 111 text

@mheap 1 0 0 Load Balancer 1 0 2

Slide 112

Slide 112 text

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

Slide 113

Slide 113 text

@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

Slide 114

Slide 114 text

@mheap Deployment techniques

Slide 115

Slide 115 text

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

Slide 116

Slide 116 text

@mheap Announce releases

Slide 117

Slide 117 text

@mheap Staggered Releases

Slide 118

Slide 118 text

@mheap Canary deploys

Slide 119

Slide 119 text

@mheap Go / No Go

Slide 120

Slide 120 text

@mheap Containers

Slide 121

Slide 121 text

@mheap Chatops

Slide 122

Slide 122 text

@mheap Summary

Slide 123

Slide 123 text

@mheap Automate your deployment

Slide 124

Slide 124 text

@mheap Local builds

Slide 125

Slide 125 text

@mheap Immutable releases

Slide 126

Slide 126 text

@mheap Think about deployment before you write any code

Slide 127

Slide 127 text

@mheap The three strikes rule

Slide 128

Slide 128 text

@mheap Make it a single command

Slide 129

Slide 129 text

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

Slide 130

Slide 130 text

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